概述
第一天也是第一次写博客,跟的b站学习,然后推荐要写写博客,当作一个小日记,如果后期真的要从事这方面的话,只当这是一段美好的学习经历,就跟拍照一样,留个小纪念。这些东西虽然写着挺费时间的,但是它能帮你更好理解一个小项目吧,你不能光看视频,更是要动手实践,一看就会,一做就废。前期肯定是痛苦的,打好基础吧,为了位数不多的希望吧!!
main函数
进行一个大概的设计,首先是一个菜单的打印,看起来更加美观,然后则是选择做游戏或者退出游戏,一个do while循环,如果输入1则是选择做游戏进行下一个game函数,选择0的话是退出游戏,其他数字会提示输入错误,重新选择while的循环条件只要不是0则一直进行循环语句。
#include <stdio.h> int main() { int input=0; do{ menu();//菜单函数 printf("请选择:->\n"); scanf("%d",&input); //输入1做游戏,0则是退出,其他数字重新选择do while循环继续 switch(input){ case 1: game();//game 游戏函数 break; case 0: printf("退出游戏\n"); break; default: printf("输入错误,请重新选择\n"); break; } }while(input); return 0; }
菜单函数是以下代码块儿 因为是初始化的格式,就把它放入main函数里了,纯是为了记录下。第一次写,就这样吧。
第一行是为了函数一个声明可以放在main函数前面 类型是void需要返回值,然后下面的是具体的函数内容可以放在main函数后面 ,个人觉得这样更美观。
void menu(); void menu(){ printf("#################################\n"); printf("###########1.play 0.exit#########\n"); printf("#################################\n"); }
game函数;
下棋前要先打印个棋盘,棋盘打印后实现玩家下棋,紧接着电脑下棋,每次下一步就要存储这个棋子后打印棋盘,直至某一行、某一列或者对角线三个相连,或者就是棋盘下满后平局。game函数包含(InitBoard)初始化棋盘、(DisplayBoard)打印棋盘、(PlayerMove)玩家下棋、(ComputerMove)电脑下棋
InitBoard初始化棋盘
初始化一个棋盘用字符类型的二维数组进行初始化。我们用一个define 定义宏 设置row 行为3,col列为3。用空格字符填充棋盘,后面下棋则用别的字符进行赋值。该功能主要用于初始化棋盘。
void InitBoard(char board[ROW][COL],int row,int col); //初始化棋盘
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]=' ';
}
}
}
DisplayBoard打印棋盘
这一部分要打印棋盘然后还是传递这个二维字符数组,通过行和列打印棋盘此时需要打印一些分割符号用于美观。
这里说一下分割符号,首先它是一个3x3的矩阵,存储为空格字符的时候前后都留有一个空格为了让后面的棋子看起来居中,然后通过循环将第一列和第二列以及第二列和第三列中间打印一个'|'符号用于分割,因为是j<col-1 所以只会执行两次 就是两列 如果将宏改成别的数字的话,比如一个5x5的矩阵,通过j-1会打印到第4列而不会在最后一列后面打印
这里的形式参数都是通过自定义的ROW COL传递过来,想改变数字就在最开始定义的头文件那里的define后面的数字改变。 然后说一下行,行和列是同样的道理,不过区别就在每行之间还需要3个'-'然后效果类似下图。
void DisplayBoard(char board[ROW][COL],int row,int col);//声明打印棋盘函数
void DisplayBoard(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){
int j=0;
for(j=0;j<col;j++){
printf("---");
if(j<col-1){
printf("|");
}
}
printf("\n");
}
}
}
PlayerMove玩家下棋
目前开始玩家下棋,我们用坐标来表示该棋子的位置,x和y两个变量,做一个循环语句,3x3的矩阵,先判断输入的是不是(1,1)、(1,2)、(1,3)、(2,1)、(2,2)、(2,3)、(3,1)、(3,2)、(3,3)这9个坐标,如果不是即超出范围提示非法输入请重新选择。如果正常的话就将该坐标赋值成'*'字符用于表示玩家下的棋子。
这里要注意因为我们的坐标是1,1的话就表示二维数组的第一个下标为0,0的元素 所以这里先判断该位置是否是空格字符用一个if条件语句来判定条件是x-1,y-1 这个位置表示才是下标为0,0的元素即二维数组第一个元素,如果该位置不是空格的话则证明坐标被占用需要重新选择。
void PlayerMove(char board[ROW][COL],int row,int col); //玩家下棋
void PlayerMove(char board[ROW][COL],int row,int col) //玩家下棋
{
int x=0,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;
}else{
printf("坐标被占用,不能下棋,请选其他位置\n");
}
}else{
printf("非法输入,请重新输入\n");
}
}
}
ComputerMove电脑下棋
我们用一个srand函数 然后将当前时间传进去该时间类型转化成unsigned int无符号整形后time函数的参数设置为空,即生成一个随机数的起点。
#include <time.h> #include <stdlib.h> srand((unsigned int)time(NULL)); //设置随机数的生成起点 x=rand()%row; //0~2 y=rand()%col; //0~2
在ComputerMove函数用引用随机数对3取余数生成的范围是0~2,此时刚好满足电脑在不是空格处进行下棋,用'#'表示。
void ComputerMove(char board[ROW][COL],int row,int col); //电脑下棋
void ComputerMove(char board[ROW][COL],int row,int col) //电脑下棋
{
printf("电脑下棋:->\n");
int x=0;
int y=0;
while(1){
x=rand()%row; //0~2
y=rand()%col; //0~2
if(board[x][y]==' '){
board[x][y]='#';
break;
}
}
}
IsWin函数判断输赢
每次玩家和电脑下棋后都判断一次是否连成3个,行、列和对角线只要满足3个就证明一方赢,这个函数返回一个字符'*'代表玩家赢, '#'代表电脑赢 ,'Q'代表平局,'c'代表游戏继续。在game函数中引用这PlayerMove、ComputerMove两个函数后都判断一次,这里紧挨着需要判断下棋盘是否满了,如果下完后发现没有连成3个或没有空格字符则证明平局。
char IsWin(char board[ROW][COL],int row,int col); //判断输赢
char IsWin(char board[ROW][COL],int row,int col){
//行
int i=0;
int j=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][1];
}
}
//列
for(j=0;j<col;i++){
if(board[0][j]==board[1][j]&&board[1][j]==board[2][j]&&board[1][j]!=' '){
return board[1][j];
}
}
//对角线
if(board[0][0]==board[1][1]&&board[1][1]==board[2][2]&&board[1][1]!=' '){
return board[1][1];
}
if(board[0][2]==board[1][1]&&board[1][1]==board[2][0]&&board[1][1]!=' '){
return board[1][1];
}
//没人赢,就要平局;
if(IsFull(board,row,col)){
return 'Q';
}
//游戏继续
return 'c';
}
IsFull函数
用一个IsFull函数双重for循环返回1则证明满了若没有赢家则平局,返回0游戏继续。
int IsFull(char board[ROW][COL],int row,int col); //判断是否棋盘满了
//满了返回1 不满返回0
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;
}
总代码
#include <stdio.h>
#define ROW 3
#define COL 3
#include <time.h>
#include <stdlib.h>
void menu();
void game();
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); //判断输赢
int IsFull(char board[ROW][COL],int row,int col); //判断是否棋盘满了
int main()
{
srand((unsigned int)time(NULL)); //设置随机数的生成起点
int input=0;
do{
menu();//菜单函数
printf("请选择:->\n");
scanf("%d",&input);
//输入1做游戏,0则是退出,其他数字重新选择do while循环继续
switch(input){
case 1:
game();//game 游戏函数
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误,请重新选择\n");
break;
}
}while(input);
return 0;
}
void menu(){
printf("#################################\n");
printf("###########1.play 0.exit#########\n");
printf("#################################\n");
}
void game()
{
char ret=0;
char board[ROW][COL]={0};
//初始化棋盘函数
InitBoard(board,ROW,COL);
DisplayBoard(board,ROW,COL);
while(1){
PlayerMove(board,ROW,COL);
ret=IsWin(board,ROW,COL);
if(ret!='c'){
break;
}
DisplayBoard(board,ROW,COL);
ComputerMove(board,ROW,COL);
ret=IsWin(board,ROW,COL);
if(ret!='c'){
break;
}
DisplayBoard(board,ROW,COL);
}
if(ret=='*'){
printf("玩家赢\n");
}else if(ret=='#'){
printf("电脑赢\n");
}else{
printf("平局\n");
}
DisplayBoard(board,ROW,COL);
}
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;
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){
int j=0;
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,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;
}else{
printf("坐标被占用,不能下棋,请选其他位置\n");
}
}else{
printf("非法输入,请重新输入\n");
}
}
}
void ComputerMove(char board[ROW][COL],int row,int col){ //电脑下棋
printf("电脑下棋:->\n");
int x=0;
int y=0;
while(1){
x=rand()%row; //0~2
y=rand()%col; //0~2
if(board[x][y]==' '){
board[x][y]='#';
break;
}
}
}
char IsWin(char board[ROW][COL],int row,int col){
//行
int i=0;
int j=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][1];
}
}
//列
for(j=0;j<col;j++){
if(board[0][j]==board[1][j]&&board[1][j]==board[2][j]&&board[1][j]!=' '){
return board[1][j];
}
}
//对角线
if(board[0][0]==board[1][1]&&board[1][1]==board[2][2]&&board[1][1]!=' '){
return board[1][1];
}
if(board[0][2]==board[1][1]&&board[1][1]==board[2][0]&&board[1][1]!=' '){
return board[1][1];
}
//没人赢,就要平局;
if(IsFull(board,row,col)){
return 'Q';
}
//游戏继续
return 'c';
}
//满了返回1 不满返回0
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;
}