1 : 三子棋游戏具体分析
1: 创造多个文件,三个文件分别是 (test.c,game.c,game.h)能更好处理各个文件之间的逻辑并且便于日后代码维护,也使得代码的可读性提高
2: 创造一个3*3的棋牌,同一形状连成(三格)即获胜,横排、竖 排、对角线
3: 进入游戏后先打印菜单提示
4:如果游戏想重复玩,使用do…while循环(根据输入值来确定后续的游戏进程)
2 : 实现游戏具体步骤
2:1:主函数搭建整体框架
先把这个框架在main函数搭建起来
int main() { int input = 0; do { menu(); printf("请选择->"); scanf("%d", &input); switch(input) { case 1: game(); break; case 0: break; default: printf("选择错误,请重新选择\n"); break; } } while (input); system("pause"); return 0; }
2.2:创建游戏初始界面 (进入\退出)
0作为exit,对应switch csae0, 来退出游戏,do…while不在循环
void menu() { printf("***** 1--play *****\n"); printf("***** 0--exit *****\n"); }
2.3:创造棋牌
创建一个名为board的二维数组,宏定义了ROW,COL,来创造棋牌大小
使用宏定义的原因:
1.代码可读性更好。
2.如果将来要修改棋盘尺寸,代码修改会很方便。
//创了数据多少行,多少列 char board[ROW][COL]={0};
2.4:搭建棋牌
将二维数组元素全部初始化为空格
//搭建棋牌 void Initboard(char board[ROW][COL], int row, int col) { //库函数memset来初始化 //如何算数组总大小:row*col计算个数 board[0][0]计算该元素占用多少个字节 memset(&board[0][0], ' ', row*col*sizeof(board[0][0])); }
2.5:棋牌显示
/显示棋牌 void Display(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++) { 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"); } }
2.6:玩家下棋
玩家输入行列坐标表示下棋,玩家下棋成功用 ‘*’ 来表示。
玩家下棋要在指定范围坐标里 玩家下坐标要从1开始,
若玩家输入的坐标非法或者被占用时,需要重新输入,则需要一个循环。
//玩家下棋 void player(char board[ROW][COL], int row, int col) { int x = 0; int y = 0; printf("玩家请走\n"); while (1) { printf("请选择下标->"); scanf("%d %d", &x, &y); //因为是玩家下,所以坐标要从1开始,1对应我们数组下标0 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("输入错误,坐标非法\n"); } } }
2.7:电脑下棋
电脑下棋,x,y是个随机数,所以要在主函数中调用srand((unsigned int)time(NULL))
若电脑生成随机值坐标非法或占用时,需要重新输入,则需要一个循环。
void Comperter(char board[ROW][COL], int row, int col) { int x = 0; int y = 0; while (1) { x = rand() % row;//模上row x范围在0-row-1之间 y = rand() % col;//模上col x范围在0-col-1之间 if (x >= 0 && x < row && y >= 0 && y < col)//判断坐标是否合法 if (board[x][y] == ' ')//是否是空坐标 { board[x][y] = '#';//下棋成功 break; } } }
2.8:判断输赢
判断输赢
玩家赢 返回*
电脑赢 返回#
平局 返回 Q
继续 返回 C
1:判定是否和棋
调用 Isdraw函数。如果数组中有元素为’ ‘,没满,返回1。如果全不为’ ',就是满了,返回0
由于Isdraw函数只是写给Iswin函数的,只需要在game.c这个文件内使用,所以加上static修饰
2:判定电脑玩家胜利
判定所有的行,列,对角线是否为相同形状,如果是返回其中一个坐标,返回 * 代表玩家赢, 返回# 电脑赢
是否平局 static int Isdraw(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; //返回0 继续Q //返回1 平局C for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { if (board[i][j] == ' ')//如还有空坐标就是要继续 return 1; } } return 0; } char Iswin(char board[ROW][COL], int row, int col) { int i = 0; for (i = 0; i < row; i++) { //竖三个 if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ') return board[1][i]; //行三个 else if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ') return board[i][1]; //对角 else if (board[0][0] == board[1][1] && board[1][1] == board[1][2] && board[1][1] != ' ') return board[1][1]; //对角 else if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ') return board[1][1]; } //判断是否平局还是继续 if (i == row) { //返回0 继续Q //返回1 平局C int ret = Isdraw(board, row, col); if (ret ==1) return 'C'; else return 'Q'; } }
3 : 三子棋所有代码文件
3.1 test.c
整体框架
#define _CRT_SECURE_NO_WARNINGS 1 #include"game.h" void menu() { printf("***** 1--play *****\n"); printf("***** 0--exit *****\n"); } void game() { char ret = 0; //创了数据多少行,多少列 char board[ROW][COL]={0}; //初始化棋牌: Initboard(board, ROW, COL); //显示棋牌棋牌 Display(board, ROW, COL); //下棋 while (1) { //玩家下棋 player(board, ROW, COL); Display(board, ROW, COL); //判断输赢 ret = Iswin(board, ROW, COL); //当棋局状态不是C时说明游戏结束了,就跳出循环,接着根据不同情况打印不同的结果。 if (ret != 'C') { break; } //电脑下棋 Comperter(board, ROW, COL); Display(board, ROW, COL); ret = Iswin(board, ROW, COL); //当棋局状态不是C时说明游戏结束了,就跳出循环,接着根据不同情况打印不同的结果。 if (ret != 'C') { break; } } if (ret == '*') { printf("玩家赢\n"); } else if (ret == '#') { printf("电脑赢\n"); } else printf("平局\n"); } int main() { srand((unsigned int)time(NULL)); int input = 0; do { menu(); printf("请选择->"); scanf("%d", &input); switch(input) { case 1: game(); break; case 0: break; default: printf("选择错误,请重新选择\n"); break; } } while (input); system("pause"); return 0; }
3.2 game.c
#define _CRT_SECURE_NO_WARNINGS 1 #include"game.h" //初始化棋牌 void Initboard(char board[ROW][COL], int row, int col) { //循环方式来初始化 //int i = 0; //for (i = 0; i < row; i++) //{ // int j = 0; // for (j = 0; j < col; j++) // { // board[i][j] = ' '; // } //} //库函数memset来初始化 //如何算数组总大小:row*col计算个数 board[0][0]计算该元素占用多少个字节 memset(&board[0][0], ' ', row*col*sizeof(board[0][0])); } //显示棋牌 //void Display(char board[ROW][COL], int row, int col) //{ // //打印固定写死了,要在优化 // int i = 0; // int j = 0; // for (i = 0; i < row; i++) // { // printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]); // if (i < row - 1) // printf("---|---|---\n"); // // } //} //显示棋牌 void Display(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++) { 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 player(char board[ROW][COL], int row, int col) { int x = 0; int y = 0; printf("玩家请走\n"); while (1) { printf("请选择下标->"); scanf("%d %d", &x, &y); //因为是玩家下,所以坐标要从1开始,1对应我们数组下标0 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("输入错误,坐标非法\n"); } } } //电脑下棋 void Comperter(char board[ROW][COL], int row, int col) { int x = 0; int y = 0; while (1) { x = rand() % row;//模上row x范围在0-row-1之间 y = rand() % col;//模上col x范围在0-col-1之间 if (x >= 0 && x < row && y >= 0 && y < col)//判断坐标是否合法 if (board[x][y] == ' ')//是否是空坐标 { board[x][y] = '#';//下棋成功 break; } } } 是否平局 static int Isdraw(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; //返回0 继续Q //返回1 平局C for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { if (board[i][j] == ' ')//如还有空坐标就是要继续 return 1; } } return 0; } //判断输赢 char Iswin(char board[ROW][COL], int row, int col) { int i = 0; for (i = 0; i < row; i++) { //竖三个 if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ') return board[1][i]; //行三个 else if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ') return board[i][1]; //对角 else if (board[0][0] == board[1][1] && board[1][1] == board[1][2] && board[1][1] != ' ') return board[1][1]; //对角 else if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ') return board[1][1]; } //判断是否平局还是继续 //判断是否平局还是继续 if (i == row) { //返回1 平局Q //返回0 继续C int ret = Isdraw(board, row, col); if (ret ==1) return 'Q'; } return 'C'; } }
3.3 game.h
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<time.h> #define ROW 3 #define COL 3 //程序化棋牌 void Initboard(char board[ROW][COL], int row, int col); //显示棋牌 void Display(char board[ROW][COL], int row ,int col); //玩家下棋 void player(char board[ROW][COL], int row, int col); //电脑下棋 void Comperter(char board[ROW][COL], int row, int col); //判断输赢 //玩家赢 返回* //电脑赢 返回# //平局 返回 Q //继续 返回 C char Iswin(char board[ROW][COL], int row, int col);