该游戏的编程比较简单,但听课学会和自己打出来做出来是两个东西,博主也是犯了不少错误。(笔者使用的是vs2019),在编译器笔者已经使用了优化(即_CRT_SECURE_NO_WARNINGS
到C/C++编译器里)。
下面就是枯燥的代码块笔者构造了两个cpp文件和一个.h文件
test.c.cpp wbgts.cpp test.h
首先是头文件,宏的定义使得代码可维护性增强,在更改时比如我想做五子棋,那么只需改变宏的量,即可全体改变
十分方便。但是笔者写的比较low,因为函数部分仅针对三子棋构造,因此仅仅通过改变宏,是无法实现五子棋的
,所以感兴趣的小伙伴可以大胆尝试五子棋的编译。
头文件:test.h(建议将所有函数声明或者头文件,宏定义都放到头文件以加快代码运行,优化程序)
#pragma once #include<stdio.h> #include<stdlib.h> #include<time.h> #define Row 3 #define Col 3 void InitBoard(char Board[Row][Col], int row, int col); void DisplayBoard(char Board[Row][Col], int row, int col); void PlayerMove(char Board[Row][Col],int row,int col); void ComputerMove(char Board[Row][Col],int row,int col); char Is_Win(char Board[Row][Col], int row, int col);
函数部分(代码与代码之间环环相扣)
#include"test.h" void InitBoard(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { board[i][j] = ' '; } } } void DisplayBoard(char board[ROW][COL], int row, int col) { int i = 0; for (i = 0; i < row; i++) { //1.打印一行的数据 //printf(" %c | %c | %c \n",board[i][0],board[i][1],board[i][2]); //2.打印分割行 int j = 0; for (j = 0; j < col; j++) { printf(" %c ", board[i][j]); if(j<col-1) printf("|"); } printf("\n"); if (i < row - 1) { for (j = 0; j < col; j++) { printf("---"); if (j < col - 1) printf("|"); } printf("\n"); } } }//这个代码写的比较low,比较僵化,当换n*n行就会得不到宫格 void PlayerMove(char board[ROW][COL], int row, int col) { int x = 0; int y = 0; printf("玩家走:>\n"); while (1) { printf("请输入要下的坐标:>"); scanf_s("%d%d", &x, &y); //判断x,y坐标的合法性 if (x >= 1 && x <= row && y >= 1 && y <= col) { if (board[x - 1][y - 1] == ' ') { board[x - 1][y - 1] = '*'; break; } else { printf("该坐标被占用\n"); } } else { printf("坐标非法,请重新输入:>"); } } } void ComputerMove(char board[ROW][COL], int row, int col) { int x = 0; int y = 0; printf("电脑走:>\n"); while (1) { x = rand() % row; y = rand() % col; if (board[x][y] == ' ') { board[x][y] = '#'; break; } } } int IsFull(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { if (board[i][j] == ' ') { return 0;//没满 } } } return 1;//满了 } //通过字符告诉我们四种游戏的状态 //玩家赢 '*' //电脑赢 '#' //平局 'Q' //继续 'C' char IsWin(char board[ROW][COL], int row, int col) { //判断横三行 int i = 0; for (i = 0; i < row; i++) { if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ') { return board[i][0]; } } //判断竖三列 for (i = 0; i < col; i++) { if (board[0][i] == board[1][i] && board[2][i] == board[1][i] && board[1][i] != ' ') { return board[1][i]; } } //两个对角线 if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ' || board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[2][2] != ' ') { return board[1][1];//这个中间数使得便利,要善于运用发掘的可优化代码的条件 } //判断是否平局 //返回:1表示棋盘满了;;0表示棋盘没满 if(1 == IsFull(board, ROW, COL)) { return 'Q'; } else return 'C'; }
主题main函数的构造
test.c.cpp #include"test.h" void game() { char Board[Row][Col] = { 0 }; char ret; //初始化棋盘 InitBoard(Board, Row, Col); //打印棋盘 DisplayBoard(Board, Row, Col); while (1) { PlayerMove(Board, Row, Col); //玩家每走一步都要打印出来显示并且判断胜负 DisplayBoard(Board, Row, Col); ret = Is_Win(Board, Row, Col); if (ret!='C') { break; } //电脑每走一步都要打印出来显示以供玩家参考 ComputerMove(Board, Row, Col); DisplayBoard(Board, Row, Col); ret= Is_Win(Board, Row, Col); if (ret != 'C') { break; } } if (ret == '*') { printf("玩家胜利\n"); } else if (ret == '#') { printf("电脑胜利\n"); } else printf("平局\n"); } void menu() { printf("***************************\n"); printf("***** 1.play 0.exit *****\n"); printf("***************************\n"); } void test() { int input = 0; do { menu(); printf("请选择:>\n"); srand((unsigned int)time(NULL)); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出成功\n"); break; default: printf("输入错误,请重新选择\n"); break; } } while (input); } int main() { test(); return 0; }