目录
前言
在哔哩哔哩上比特鹏哥的课程上学习C++的时候看见了一个三子棋的编程教学,本着跟着学一学项目编写的目的跟着编写了一部分,在看到电脑落子是随机的的时候决定剩下的自己写,于是把原来的三子棋拓展为了一个标准的五子棋,并自行编写了判断是否游戏结束的函数。运行效果还行,发出来纪念一下,第一个半自主编写的小项目
提示:以下是本篇文章正文内容,下面案例可供参考
一、引用头文件
该项目引用了iostream和stdio.h两个头文件
#include <stdio.h>
#include <iostream>
using namespace std;
其实本来只用引入<:stdio.h>的,但是不知道为什么scanf函数出了些问题,就不得不改用cin做次级替代了。
二、代码
啥都不说了直接贴代码吧。
1、主函数
主函数基本和鹏哥的一致。
#define _CPR_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include "game.h"
#include <iostream>
using namespace std;
//#include "game.c"
void menu()
{
printf("______________________________\n");
printf("____________五子棋____________\n");
printf("____________1.play____________\n");
printf("____________0.exit____________\n");
printf("___________by__Weber__________\n");
printf("______________________________\n");
}
void game()
{
char board[ROW][COL];
InitBoard(board,ROW,COL);
DisplayBoard(board,ROW,COL);
while(1)
{
Player1Move(board,ROW,COL);
DisplayBoard(board,ROW,COL);
// cout<<Check1Done(board,ROW,COL)<<endl;
if(Check1Done(board,ROW,COL))
{
printf("玩家1胜利\n");
break;
}
Player2Move(board,ROW,COL);
DisplayBoard(board,ROW,COL);
if(Check2Done(board,ROW,COL))
{
printf("玩家2胜利\n");
break;
}
}
}
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");
break;
}
} while (input);
return 0;
}
2、头文件
通过改变头文件中定义的三个值,可以改变棋盘的长宽(不过建议这两个值保持一致,后面写的时候有点写糊涂了,两个值不一样可能导致函数出错)和获胜条件(五子相连)。
#define ROW 21
#define COL 21
#define N 5
//初始化棋盘
void InitBoard(char board[ROW][COL],int row,int col);
//打印棋盘
void DisplayBoard(char board[ROW][COL],int row,int col);
//player1下棋
void Player1Move(char board[ROW][COL],int row,int col);
// player2下棋
void Player2Move(char board[ROW][COL],int row,int col);
//确认是否游戏结束
bool Check1Done(char board[ROW][COL],int row,int col);
bool Check2Done(char board[ROW][COL],int row,int col);
3、函数文件
从上到下函数依次为:
1、清空棋盘(二维数组)
2、展示棋盘(输出二维数组)
3 4、玩家1、2落子(我把鹏哥的电脑做成了玩家2,由于要区分*和#所以写了两个)
5 6、检测玩家1、2是否达成胜利条件(两个函数,原因同上),四个循环嵌套,分别扫描行列和左斜、右斜
#include "game.h"
#include <stdio.h>
#include <iostream>
using namespace std;
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++)
{
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");
}
}
}
void Player1Move(char board[ROW][COL],int row,int col)
{
int x = 0;
int y = 0;
while(1)
{
printf("玩家1走>\n");
//printf("输入样例<num> <num>\n");
printf("请输入下棋坐标:>\n");
//scanf("%d %d,&x,&y");
cout<<"x=";
cin>>x;
cout<<"y=";
cin>>y;
cout<<endl;
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 Player2Move(char board[ROW][COL],int row,int col)
{
int x = 0;
int y = 0;
while(1)
{
printf("玩家2走>\n");
//printf("输入样例<num>*<num>\n");
printf("请输入下棋坐标:>\n");
//scanf("%d*%d,&x,&y");
cout<<"x=";
cin>>x;
cout<<"y=";
cin>>y;
cout<<endl;
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");
}
}
}
bool Check1Done(char board[ROW][COL],int row,int col)
{
for(int i=0;i<ROW;i++)
{
int count = 0;
for(int j=0;j<COL;j++)
{
if(board[i][j]=='*')
{
count++;
if(count==N)
{
return(1);
}
}
else
{
count = 0;
}
}
}
for(int i=0;i<ROW;i++)
{
int count = 0;
for(int j=0;j<COL;j++)
{
if(board[j][i]=='*')
{
count++;
if(count==N)
{
return(1);
}
}
else
{
count = 0;
}
}
}
for(int i=-ROW+1;i<=ROW-1;i++)
{
int count = 0;
for(int j=0;j<ROW;j++)
{
if((i+j>=0)&&(i+j<ROW))
{
if(board[i+j][j]=='*')
{
count++;
if(count==N)
{
return(1);
}
}
else
{
count = 0;
}
}
}
}
for(int i=0;i<(2*ROW-1);i++)
{
int count = 0;
for(int j=0;j<COL;j++)
{
if((i-j>=0)&&(i-j<ROW))
{
if(board[i-j][j]=='*')
{
count++;
if(count==N)
{
return(1);
}
}
else
{
count = 0;
}
}
}
}
return(0);
}
bool Check2Done(char board[ROW][COL],int row,int col)
{
for(int i=0;i<ROW;i++)
{
int count = 0;
for(int j=0;j<COL;j++)
{
if(board[i][j]=='#')
{
count++;
if(count==N)
{
return(1);
}
}
else
{
count = 0;
}
}
}
for(int i=0;i<ROW;i++)
{
int count = 0;
for(int j=0;j<COL;j++)
{
if(board[j][i]=='#')
{
count++;
if(count==N)
{
return(1);
}
}
else
{
count = 0;
}
}
}
for(int i=-ROW+1;i<=ROW-1;i++)
{
int count = 0;
for(int j=0;j<ROW;j++)
{
if((i+j>=0)&&(i+j<ROW))
{
if(board[i+j][j]=='#')
{
count++;
if(count==N)
{
return(1);
}
}
else
{
count = 0;
}
}
}
}
for(int i=0;i<(2*ROW-1);i++)
{
int count = 0;
for(int j=0;j<COL;j++)
{
if((i-j>=0)&&(i-j<ROW))
{
if(board[i-j][j]=='N')
{
count++;
if(count==N)
{
return(1);
}
}
else
{
count = 0;
}
}
}
}
return(0);
}
三、编写时出现的问题
由于最开始的底层逻辑并不是由本人搭建的,在实现函数5、6时不得不采取全程扫描的方法,浪费了很多算力,如果能输入上一落子的类型和坐标,就能将5、6合并,去除循环嵌套并直接进行米字型计数,然而没有实现,这是很可惜的一点。
总结
这是我第一次编写项目,主要还是熟悉各种文件类型和编写范式,跨文件调用方法,以及编写项目的大局观、思考方式。总的来说,是一次非常值得的尝试。