湖北省建设厅网站怎么打不开,昆明信息港官网,成都装修公司一览表,企业建网站租用服务器好还是买一个好注#xff1a;在最后面#xff0c;完整源码会以两种形式展现。在讲解时#xff0c;以三个源文件的形式。 前言#xff1a;三子棋#xff0c;顾名思义#xff0c;就是三个子连在一起就可以胜出。在本节我们要介绍的三子棋模式是这样子的#xff1a;在键盘输入坐标#x…注在最后面完整源码会以两种形式展现。在讲解时以三个源文件的形式。 前言三子棋顾名思义就是三个子连在一起就可以胜出。在本节我们要介绍的三子棋模式是这样子的在键盘输入坐标表示落子和电脑对下当前电脑设计为随机下。
我们先看游戏执行起来的样子 全局思路下棋肯定需要一个棋盘不然会显得杂乱无章当有了棋盘之后就需要落子落子需要双方一个是我们自己手动下另一个就是电脑设置自动下当每一次落子都需要判断是否输赢否则重复落子步骤循环而判断输赢也作为一块内容。因为作为小游戏肯定需要一个游戏菜单。 思路简图设置菜单------设置棋盘-------玩家落子---电脑落子------判断输赢 三子棋流程图 上面是铺垫接下来才是重头戏该上强度了。 一、准备工作和游戏菜单
在第一个源文件test.c和头文件game.h中实现
1.准备工作
1建立两个源文件和一个头文件
目的方便观察和日后的工作不展开
2建立三个文件的联系大致雏形 上面的信息大致可以让我们知道每个文件大致要存放的内容关于引用头文件这些知识不是我们现阶段需要明白的只需记住这样用就行。
2.游戏菜单
1菜单的模板
void menu()//菜单函数
{printf(####################\n);printf(###### 1.play ######\n);printf(###### 0.exit ######\n);printf(####################\n);
}
int main()
{int input 0;do//循环菜单{menu();printf(请选择:);scanf(%d,input);} while (input);return 0;
}
运行结果 1.我们把菜单封装成一个函数放在第一个源文件中。 2.当调用完菜单之后会有两个选择这个时候就需要输入数据这就需要用到scanf函数。 3.因为当结束一局游戏后会再次出现菜单让我们选择继续与否所以要用到do…while循环因为这样至少会执行一次菜单。 2输入数据后的选择与判断 当我们用scanf函数输入数据后就需要根据输入的数据选择不同的路径。
void menu()//菜单函数
{printf(####################\n);printf(###### 1.play ######\n);printf(###### 0.exit ######\n);printf(####################\n);
}
int main()
{int input 0;do//循环菜单{menu();printf(请选择:);scanf(%d,input);switch (input)//用switch来判断选择{case 1:printf(你已选择继续游戏\n);break;case 0:printf(你已选择退出游戏\n);break;default:printf(选择错误重新选择\n);//防止乱选}} while (input);return 0;
}
运行结果
选择1 选择0 选择其他 根据输入数据的选择我们就需要用到switch函数来判断。 3继续游戏后的选择 为了选择1之后就直接可以进入游戏所以我们在后面直接跟上game函数然后在game中函数调用各种函数接口。
void menu()//菜单函数
{printf(####################\n);printf(###### 1.play ######\n);printf(###### 0.exit ######\n);printf(####################\n);
}
void game()
{char board[ROW][COL];InitBoard(board,ROW,COL);//初始化棋盘DisplayBoard(board,ROW,COL);//打印棋盘//落子循环
}
int main()
{int input 0;do//循环菜单{menu();printf(请选择:);scanf(%d,input);switch (input){case 1:printf(你已选择继续游戏\n);game();break;case 0:printf(你已选择退出游戏\n);break;default:printf(选择错误重新选择\n);}} while (input);return 0;
}
#includestdio.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); 在我们的game函数内放的是一些接口功能暂未实现。 我们需要用到二维数组然后它的行和列需要用到宏定义的常量。如果后续需要更改棋盘的大小也会很方便。 接下来我们再一一实现每个函数的功能吧
二、初始化和打印棋盘
在第二个源文件game.c中实现函数体内部的功能。
1.初始化棋盘
//初始化函数
InitBoard(board,ROW,COL);
初始化因为刚开始的棋盘是空的只需要全部赋值成空格就好。
//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col)
{int i 0;for (i 0; i row; i){int j 0;for (j0;jcol;j){board[i][j] ;//全部初始化成空格}}
}
我们可以通过调试窗口中的监视观察数组是否被成功赋值。 知识点二维数组赋值 2.打印棋盘
//打印棋盘函数
DisplayBoard(board,ROW,COL);
如果直接将初始化好的字符数组打印出来是看不见的但是呢我们可以先将空格换成其他可以看见的符号从而可以检验我们的“打印棋盘函数”是否写对了。
要想打印出下面的这个棋盘该怎么做呢 这是一个九宫格其实这个棋盘有五行五列。第一行是空格和竖线组成第二行是横线和竖线组成组成后面同理。 我们可以有很多种方式打印我们列举一种 1.我们可以一行一行的打印出来打印完一行就换行。 2.竖线有两行横线也只有两行他们只能打印两次。 3.数组打印三行三列横线打印两行竖线打印两行。 打印棋盘函数
//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col)
{int i 0;for (i0;irow;i)//控制行的个数{//打印数组和竖线int j 0;for (j0;jcol;j)//控制列的个数{printf( %c ,board[i][j]);if (jcol-1)printf(|);}printf(\n);//打印完换行//打印横线用减号代替和竖线if (i row - 1){for (j 0; j col; j){printf(---);if (j col - 1)printf(|);}}printf(\n);}
}
运行结果 第一层循环控制行那不是五行吗为什么这里只循环三次因为有第二层循环的控制。
总结第一次循环第一层打印三次空格和两个竖线第二层循环第二层循环没有结束继续换行打印横线和竖线这里需要注意每一行需要打印三次横线第二次循环必须循环三次但是只打印两横第一层循环只能打印两次而每一行只打印两次竖线并且只打印两行。 三、玩家与电脑的落子
1.玩家落子*
因为我们所输入的坐标是从1开始而数组的下标是从0开始所以需要区别
void PlayerMove(char board[ROW][COL], int row, int col)
{int x 0;int y 0;printf(请输入要落子的位置\n);while (1){printf(玩家下:);scanf(%d%d, x, y);//输入下棋的坐标//判断落子位置是否合法if (x 1 x 3 y 1 y 3){//判断落子位置是否被占用if (board[x - 1][y - 1] ){board[x - 1][y - 1] *;break;}elseprintf(该位置已被占用请重新输入\n);}elseprintf(落子位置非法\n);}
}
总结落子时考虑位置是否合法坐标是否被占否则重新循环最后再落子落子完成再退出循环。 知识点选择语句的条件判断与数字下标的运用 2.电脑落子#
电脑落子则是需要随机产生数字作为坐标再落子所以我们需要用到产生随机数的知识点。
生成随机数
#includestdlib.h//srand所需头文件
#includetime.h//time所需头文件
srand((unsigned)time(NULL));
int xrand();//此时x中的值就是随机值 其中srand函数和rand函数是配合使用的。 srand函数只需要在主函数中提到一次srand函数中的参数设为时间返回一个NULL并强制类型转化。我们当前只需要计熟这句话就行。 然后我们就可以使用rand函数来产生随机数了只需要用变量来接收即可。 当前头文件
#includestdio.h
#includestdlib.h
#includetime.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);当前源文件test.c:
#includegame.h
void menu()//菜单函数
{printf(####################\n);printf(###### 1.play ######\n);printf(###### 0.exit ######\n);printf(####################\n);
}
void game()
{char ret 0;char board[ROW][COL];InitBoard(board,ROW,COL);//初始化棋盘DisplayBoard(board,ROW,COL);//打印棋盘PlayerMove(board, ROW, COL);DisplayBoard(board, ROW, COL);//打印棋盘ComputerMove(board,ROW,COL);DisplayBoard(board, ROW, COL);//打印棋盘}
int main()
{int input 0;srand((unsigned)time(NULL));do//循环菜单{menu();printf(请选择:);scanf(%d,input);switch (input){case 1:printf(你已选择继续游戏\n);game();break;case 0:printf(你已选择退出游戏\n);break;default:printf(选择错误重新选择\n);}} while (input);return 0;
}
电脑落子函数:
//电脑落子
void ComputerMove(char board[ROW][COL], int row, int col)
{printf(电脑落子:\n);int x 0;int y 0;while (1){x rand() % row;y rand() % col;//范围0-2if (board[x][y] ){board[x][y] #;//满足就落子否则继续循环break;}}
} 上面的落子函数虽然已经写完但是运行起来还是很不完整的接下来的判赢才是重头戏。 四、判断输赢与循环落子
1.判赢
游戏的大致走向有四种继续游戏、玩家赢、电脑赢和平局。其中继续游戏就是循环落子的原因知道出现一个结局。
判赢函数
char Iswin(char board[ROW][COL], int row, int col)
我们这里规定一下根据该函数的返回值来决定四种结果
//*--玩家赢 #----电脑赢 P----平局 C-----游戏继续
判赢
三子棋游戏胜利的结果就是三个子连成一条线。三子连成线的结果无非就是三种横、竖和斜的。
//*--玩家赢 #----电脑赢 P----平局 C-----继续
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[0][i] ! )return board[0][i];}for (i 0; i col; i)//三列相等的{if (board[i][0] board[i][1] board[i][1] board[i][2] board[i][0] ! )return board[i][0];}//判断\相等if (board[0][0] board[1][1] board[1][1] board[2][2] board[1][1] ! )return board[1][1];//判断/相等if (board[2][2] board[1][1] board[1][1] board[0][0] board[1][1] ! )return board[1][1];return C;
} 1.前面两个for循环判断横与列是否相等如果相等就返回某一个坐标的值。 2.后面两个if语句同样的效果满足条件就返回某个坐标。 3.如果上面的都不满足则会返回C也就是游戏继续 上面的代码还差一种结局那就是平局。平局的条件莫非就是棋盘满了但是还没有分出胜负所以我们另外封装一个判满的函数即可。在上面的代码基础上改进
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;}
//*--玩家赢 #----电脑赢 P----平局 C-----继续
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[0][i] ! )return board[0][i];}for (i 0; i col; i)//三列相等的{if (board[i][0] board[i][1] board[i][1] board[i][2] board[i][0] ! )return board[i][0];}//判断\相等if (board[0][0] board[1][1] board[1][1] board[2][2] board[1][1] ! )return board[1][1];//判断/相等if (board[2][2] board[1][1] board[1][1] board[0][0] board[1][1] ! )return board[1][1];//判断平局if (IsFull(board, row, col))return P;return C;
}
现在代码完整了只要不满足输赢或者平局游戏就会继续。
现在函数体的内容都已经完成接下来需要在主函数实现接收其返回值并实现循环落子。
2.用循环实现游戏继续
其实就是每下一次就打印一次棋盘并且判断一次游戏是否继续
char ret0;
while (1){//玩家下棋PlayerMove(board, ROW, COL);DisplayBoard(board, ROW, COL);//打印棋盘//每走一步棋就判断一次ret Iswin(board,ROW,COL);if (ret ! C)//C!C为假不会跳出循环break;//电脑下棋ComputerMove(board, ROW, COL);DisplayBoard(board, ROW, COL);//打印棋盘//判断电脑输赢ret Iswin(board,ROW,COL);if (ret ! C)break;}//跳出循环表示博弈结束并判断结局if (ret *)printf(恭喜玩家获胜,再来一局吧\n);if (ret #)printf(电脑获胜再来一局吧\n);if (ret P)printf(恭喜平局谁也没有获胜\n);
到这里每个阶段的内容就完成了接下来是总体的代码。 五、完整源码
1.分装成三个文件的源码
1头文件(game.h)
#includestdio.h
#includestdlib.h
#includetime.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);
(2)源文件game.c
#includegame.h
//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col)
{int i 0;for (i 0; i row; i){int j 0;for (j0;jcol;j){board[i][j] ;//全部初始化成空格}}
}
//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col)
{int i 0;for (i0;irow;i)//控制行的个数{//打印数组和竖线int j 0;for (j0;jcol;j)//控制列的个数{printf( %c ,board[i][j]);if (jcol-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)
{int x 0;int y 0;printf(请输入要落子的位置\n);while (1){printf(玩家下:);scanf(%d%d, x, y);//输入下棋的坐标//判断落子位置是否合法if (x 1 x 3 y 1 y 3){//判断落子位置是否被占用if (board[x - 1][y - 1] ){board[x - 1][y - 1] *;break;}elseprintf(该位置已被占用请重新输入\n);}elseprintf(落子位置非法\n);}
}
//电脑落子
void ComputerMove(char board[ROW][COL], int row, int col)
{printf(电脑落子:\n);int x 0;int y 0;while (1){x rand() % row;y rand() % col;//范围0-2if (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;}//*--玩家赢 #----电脑赢 P----平局 C-----继续
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[0][i] ! )return board[0][i];}for (i 0; i col; i)//三列相等的{if (board[i][0] board[i][1] board[i][1] board[i][2] board[i][0] ! )return board[i][0];}//判断\相等if (board[0][0] board[1][1] board[1][1] board[2][2] board[1][1] ! )return board[1][1];//判断/相等if (board[2][2] board[1][1] board[1][1] board[0][0] board[1][1] ! )return board[1][1];//判断平局if (IsFull(board, row, col))return P;return C;
}
(3)源文件test.c
#includegame.h
void menu()//菜单函数
{printf(####################\n);printf(###### 1.play ######\n);printf(###### 0.exit ######\n);printf(####################\n);
}
void game()
{char ret 0;char board[ROW][COL];InitBoard(board,ROW,COL);//初始化棋盘DisplayBoard(board,ROW,COL);//打印棋盘while (1){//玩家下棋PlayerMove(board, ROW, COL);DisplayBoard(board, ROW, COL);//打印棋盘//每走一步棋就判断一次ret Iswin(board,ROW,COL);if (ret ! C)break;//电脑下棋ComputerMove(board, ROW, COL);DisplayBoard(board, ROW, COL);//打印棋盘//判断电脑输赢ret Iswin(board,ROW,COL);if (ret ! C)break;}//跳出循环表示博弈结束并判断结局if (ret *)printf(恭喜玩家获胜,再来一局吧\n);if (ret #)printf(电脑获胜再来一局吧\n);if (ret P)printf(恭喜平局谁也没有获胜\n);
}
int main()
{int input 0;srand((unsigned)time(NULL));do//循环菜单{menu();printf(请选择:);scanf(%d,input);switch (input){case 1:printf(你已选择继续游戏\n);game();break;case 0:printf(你已选择退出游戏\n);break;default:printf(选择错误重新选择\n);}} while (input);return 0;
}
2.一个文件的源码
#includestdio.h
#includestdlib.h
#includetime.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);//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col)
{int i 0;for (i 0; i row; i){int j 0;for (j0;jcol;j){board[i][j] ;//全部初始化成空格}}
}
//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col)
{int i 0;for (i0;irow;i)//控制行的个数{//打印数组和竖线int j 0;for (j0;jcol;j)//控制列的个数{printf( %c ,board[i][j]);if (jcol-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)
{int x 0;int y 0;printf(请输入要落子的位置\n);while (1){printf(玩家下:);scanf(%d%d, x, y);//输入下棋的坐标//判断落子位置是否合法if (x 1 x 3 y 1 y 3){//判断落子位置是否被占用if (board[x - 1][y - 1] ){board[x - 1][y - 1] *;break;}elseprintf(该位置已被占用请重新输入\n);}elseprintf(落子位置非法\n);}
}
//电脑落子
void ComputerMove(char board[ROW][COL], int row, int col)
{printf(电脑落子:\n);int x 0;int y 0;while (1){x rand() % row;y rand() % col;//范围0-2if (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;}//*--玩家赢 #----电脑赢 P----平局 C-----继续
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[0][i] ! )return board[0][i];}for (i 0; i col; i)//三列相等的{if (board[i][0] board[i][1] board[i][1] board[i][2] board[i][0] ! )return board[i][0];}//判断\相等if (board[0][0] board[1][1] board[1][1] board[2][2] board[1][1] ! )return board[1][1];//判断/相等if (board[2][2] board[1][1] board[1][1] board[0][0] board[1][1] ! )return board[1][1];//判断平局if (IsFull(board, row, col))return P;return C;
}void menu()//菜单函数
{printf(####################\n);printf(###### 1.play ######\n);printf(###### 0.exit ######\n);printf(####################\n);
}
void game()
{char ret 0;char board[ROW][COL];InitBoard(board,ROW,COL);//初始化棋盘DisplayBoard(board,ROW,COL);//打印棋盘while (1){//玩家下棋PlayerMove(board, ROW, COL);DisplayBoard(board, ROW, COL);//打印棋盘//每走一步棋就判断一次ret Iswin(board,ROW,COL);if (ret ! C)break;//电脑下棋ComputerMove(board, ROW, COL);DisplayBoard(board, ROW, COL);//打印棋盘//判断电脑输赢ret Iswin(board,ROW,COL);if (ret ! C)break;}//跳出循环表示博弈结束并判断结局if (ret *)printf(恭喜玩家获胜,再来一局吧\n);if (ret #)printf(电脑获胜再来一局吧\n);if (ret P)printf(恭喜平局谁也没有获胜\n);
}
int main()
{int input 0;srand((unsigned)time(NULL));do//循环菜单{menu();printf(请选择:);scanf(%d,input);switch (input){case 1:printf(你已选择继续游戏\n);game();break;case 0:printf(你已选择退出游戏\n);break;default:printf(选择错误重新选择\n);}} while (input);return 0;
} 六、总结
1.需要掌握产生随机数的方法。
2.游戏总的是采用二维数组实现其中包括了二维数组的赋值和打印数据。
3.函数的返回值和各种循环结果、选择结构。 若上述源码有bug欢迎各位大佬留言。