接下来就是通过c语言来实现三子棋这个小游戏,这个游戏是通过分文件写的方法来实现的,这种方法可增强代码的可读性,让我们一起来康康吧!
本文如果按顺序来阅读可能不太好接受,建议阅读顺序为,由test.c的逻辑顺序读下去,遇见具体函数的实现跳转到game.c中来理解
注:
test.c文件实现游戏的逻辑 game.c文件实现游戏中操作的具体实现(封装函数的实现) game.h文件为整个游戏的头文件(用于声明)
game.h
#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 IsWin(char board[ROW][COL], int row, int col);//判断游戏状态
test.c(游戏逻辑实现)
整个游戏的逻辑从main函数开始(具体实现在代码旁的注释说明)
#include"game.h" void menu()//打印菜单 { printf("****************\n"); printf("*****1.play*****\n"); printf("*****0.exit*****\n"); printf("****************\n"); } void game() { char ret = 0;//用于记录实时游戏情况 char board[ROW][COL] = { 0 };//定义三子棋棋盘 InitBoard(board,ROW,COL);//初始化棋盘 DisplayBoard(board, ROW, COL);//打印棋盘 /* 各自下一步棋后打印棋盘,然后判断游戏进程,只有游戏结束时才会跳出循环 以下为逻辑实现,每一步操作需读者跳转到game.c文件中理解 */ while (1) { PlayerMove(board, ROW, COL);//玩家下棋 DisplayBoard(board, ROW, COL);//实时打印棋盘 ret= IsWin(board, ROW, COL);//实时判断游戏进程 if (ret != 'C')//只有返回值不是‘C’时游戏才会结束 break; ComputerMove(board, ROW, COL);//电脑下棋 DisplayBoard(board, ROW, COL);//实时打印棋盘 ret = IsWin(board, ROW, COL);//实时判断游戏进程 if (ret != 'C') break; } if (ret == '*') { printf("玩家赢了\n"); } else if (ret == '@') { printf("电脑赢了\n"); } else { printf("平局\n"); } } int main() { int input = 0; srand((unsigned int)time(NULL));//此处先不解释,后边解释 do //设置循环,每次输入一个数,1进入游戏,0退出游戏 { menu();//打印菜单 scanf("%d", &input); switch (input) { case 1: printf("开始游戏\n"); game();//如果输入1,进入游戏,游戏的进一步实现在game()函数中 break; case 0: printf("退出游戏\n"); break; default: printf("输入错误,请重新输入\n"); break; } } while (input);//如果输入0,while循环终止,退出游戏 }
game.c
初始化棋盘
需要将3*3数组先全部置成空格,才能打印出空白棋盘
void InitBoard(char board[ROW][COL], int row, int col) { for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) board[i][j] = ' '; }
打印棋盘
打印出的棋盘应为这副模样
void DisplayBoard(char board[ROW][COL], int row, int col) { int i = 0, j = 0; for (i = 0; i < row; i++)//设置循环,按行打印 { 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"); } }
玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col) { printf("玩家下棋\n"); int x=0, y=0; while (1)//设置循环,当玩家下好棋后终止循环 { printf("请输入你要下的位置>\n"); scanf("%d %d", &x, &y); if (x >= 1 && x <= ROW && y >= 1 && y <= COL)//注意数组的行列都比棋盘行列少1 { if (board[x - 1][y - 1] == ' ')//如果此处无棋,将这个位置变成‘*’ { board[x - 1][y - 1] = '*'; break;//下棋完成跳出循环 } else printf("你输入的位置已被占用,请重新输入\n"); } else printf("你输入的位置不合法,请重新输入\n"); } }
电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col) { printf("电脑下棋>\n"); int x = 0, y = 0; while (1) { x = rand() % ROW;//x,y为对3取余数的随机值即0~2 y = rand() % COL; if (board[x][y] == ' ')//如果该位置为空,将棋下于此 { board[x][y] = '@'; break; } } }
判断游戏进程
游戏结果无非三种:赢 输 平
返回不同的结果:
‘C’继续游戏
‘Q’平局
‘*’玩家赢
‘@’电脑赢
static IsFull(char board[ROW][COL], int row, int col)//判断棋盘是否满了 { for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { if (board[i][j] == ' ') return 0; } } return 1; } 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][2] != ' ') return board[i][2]; } for (i = 0; i < col; i++)//列 { if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[2][i] != ' ') return board[2][i]; } //对角线 if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[2][2] != ' ') return board[1][1]; if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[2][0] != ' ') return board[1][1]; /* 行 列 对角线都是返回的对应图案,及对应不同玩家赢得游戏 */ if (IsFull(board, ROW, COL))//如果没有分出胜负但是棋盘满了,则为平局 return 'Q'; return 'C';//如果前边都没有返回,就返回'C',继续游戏 }