目录
五一小长假之后还是要继续努力了呢,来个鸡汤🍜

我们要写的是一个三子棋小游戏,也就是我们常说的井字棋。接下来盘一盘,我们需要那些部分来写成这个小程序。
这就是我们在写这个小游戏前想到需要写的东西,分开成每个部分其实都不难(循环、二位数组、判断语句)就是小小的组合了一下。
这里我们采用的是分头文件、源文件的写法,顺便附上教程链接:程序的分文件写法及注意事项

在这里我构建了三个文件,game.h文件存放函数的声明、game.c函数存放函数的定义、三子棋.c文件是程序的实现必不可少的部分。(这里不懂也不影响往下面看的)
#include<stdio.h>
#include<time.h>//下文解释,实现人机将会用到
#include<stdlib.h>//实现人机部分用到
#define ROW 3//定义棋盘的行
#define COL 3//定义棋盘的列
void menu();//给菜单的定义
void Game();//给游戏函数的定义
void InitBoard(char Broad[ROW][COL], int row, int col);//定义初始化储存二维数组的函数
void BoardDis(char broad[ROW][COL],int row,int col);//定义打印棋盘
void Player(char broad[ROW][COL], int row, int col);//定义玩家下棋的函数
void Com(char broad[ROW][COL],int row, int col);//电脑下棋的函数
char Is_win(char broad[ROW][COL], int row, int col);//判断那方获胜的函数
在这个文件里我们定义了我们写这个程序将会用到的定义,这样集中起来的一个好处是,这样程序的各个函数将会更直观的呈现出来。这里面的函数被定义出来后,将会在Game.c中声明。
这个定义不是我一口气就想出来的,是一边写一边补充的。

void menu()//游戏菜单
{
printf("*******************\n");
printf("***** 1. play *****\n");
printf("***** 0. exit *****\n");
printf("*******************\n");
}
这一部分的作用是打印出一个游戏菜单。 这个函数写在game.c文件中。
int main()
{
srand((usigned int)time(NULL));
//这个在电脑下棋那一段会用到,这里设置了一个随机数的种子
int op = 0;
do
{
menu();//菜单函数
printf("请选择\n");
scanf("%d", &op);
switch (op)
{
case 1:Game()//这个函数来将游戏实现
break;
case 0:printf("正在退出游戏\n");
break;
default:printf("输入错误,请重新输入\n");
break;
}
} while (op);//当你选择了0,循环自动结束
return 0;
}
我们的main函数值负责是否进行游戏的功能。
这里用到了switch选择结构来实现menu()函数的选择,并加了一个循环来实现重复游戏的效果。玩家在进行了一局游戏之后可以继续选择是否继续玩这个游戏。
void Game()
{
char Board[ROW][COL]={0};//储存旗子的二维数组
//给二维数组初始化的函数
//打印棋盘
while(1)
{
//玩家下棋的函数
//判断输赢的函数
//打印棋盘的函数
//电脑下棋的函数
//判断输赢的函数
//打印棋盘的函数
}
}
在这个函数中,我们会实现三子棋游戏的游戏部分。玩家下棋、电脑下棋、棋盘打印、判断输赢都会整合在这里。
void InitBoard(char board[ROW][COL], int row, int col)
{
int i = 0; int j = 0;
for (i; i < row; i++)
{
for (j=0; j < col; j++)
{
board[i][j] = ' ';
}
}
return;
}
在开始下棋前,我们将储存棋子的二维数组初始化为‘ ’(空格),这样就可以实现下面这样的效果。
每次打印出来的在我们的棋盘上其实打印的是一个空格。

我们来观察这个棋盘,实质上它是两个空格夹着我们的棋子的如下图的位置

void BroadDis(char board[ROW][COL], int row, int col)//我们需要知道要摆放什么棋子,以及棋盘的大小
{
int i = 0, j = 0;
for (i; 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");
}
}
if (j < COL-1)
printf("|");
这一部分是一个巧妙的设计,为了防止多打一个‘|’,我们在最后一次循环阻止了打印‘|’。下面这一部分也是同理:
if(i<ROW-1)
for (j=0;j<col;j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
有些同学很好奇为什么我们要在头文件宏定义一个ROW、COL,这样我们想改变棋盘大小的时候只需要改变头文件里面的数据就行了,比如:我把ROW、COL改成了10,棋盘就会变成下面这样:

这么大写个五子棋都不过分吧😁。
开始下棋咯!
void Player(char broad[ROW][COL], int row, int col)//我们要用到二维数组来储存棋子
{
int x = 0, y = 0;
printf("玩家下棋\n");
while (1)//在玩家棋子下位置前循环不会结束
{
scanf("%d %d", &x, &y);
if (x <= row && y <= col && x > 0 && y > 0)//我们的棋子不能越界
{
if (broad[x - 1][y - 1] != ' ')//我们的棋子不能占用已经棋子的位置
printf("该位置被占用\n");
else
{
broad[x-1][y-1] = '#';
break;//玩家位置下对了,训话结束
}
}
else
printf("输入的位置不合法\n");
}
}
几乎每一行都进行了标注,贼良心🎉。
🍇电脑下棋了
电脑下棋,我们这里采用随机数的方式来模拟电脑下棋。随机数的操作方法可以看看这篇文章的前小半部分(极简随机数)。
void Com(char broad[ROW][COL], int row, int col)
{
printf("电脑下棋\n");
int x = 0, y = 0;
while (1)
{
x = rand() % ROW;//给下的行数赋一个值(取余是为了控制x的大小在0~2,下同)
y = rand() % COL;//给下的列数赋一个值
if (broad[x][y] == ' ' )
{
broad[x][y] = '*';//电脑下的棋子是'*'
break;//电脑下对了才退出循环
}
}
return;
}
每下一步,我们就打印一次棋盘,现在可以来看看效果了:

我这里的思路是写一个函数判断输赢。
那我们这次定义的函数就需要是char类型的了。
char Is_win(char broad[ROW][COL], int row, int col)//把我们的棋盘导进去判断输赢
{
//在行上判断有没有人赢了
int i = 0, j = 0;
for (i = 0; i < ROW; i++)
{
//只要第一个等于第二个、第二个等于第三个就可以判定为赢,且这三个不能是空格,下同
if (broad[i][0] == broad[i][1] && broad[i][1] == broad[i][2] && broad[i][0] != ' ')
return broad[i][0];//谁赢了就返回谁的棋子
}
//在列上判断输赢
for (j = 0; j < COL; j++)
{
if (broad[0][j] == broad[1][j] && broad[1][j] == broad[2][j] && broad[0][j] != ' ')
{
return broad[0][j];
}
}
//对角线情况比较少,我就直接列出来了
if (broad[0][0] == broad[1][1] && broad[1][1] == broad[2][2]&&broad[1][1]!=' ' || broad[0][2] == broad[1][1] && broad[1][1] == broad[2][0] && broad[1][1] != ' ')
{
return broad[1][1];
}
int leap = 1;//假设棋盘满了
//是否满了,如果我们的棋盘没满就还需要继续比赛
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (broad[i][j] == ' ')
{
leap = 0;
break;
}
}
}
if (leap == 1)//棋盘满了就返回P
return 'P';
return 'N';
}
这里也有注释,应该能看懂的,要是还没看懂的话,随时私聊我🌹。
void Game()
{
char key = {0};//存放函数返回值的变量
char Broad[ROW][COL] = { 0 };//定义一个存放棋子的二维数组
InitBroad(Broad, ROW, COL);//数组初始化
BroadDis(Broad,ROW,COL);//打印棋盘
while (1)//一直下棋,知道分出胜负或平局
{
Player(Broad, ROW, COL);//玩家下棋
BroadDis(Broad, ROW, COL);//打印棋盘
key=Is_win(Broad, ROW, COL);//判断下棋结果
if (key != 'N')//棋盘没满的话我们继续下棋
break;//函数要是返回了N以外的字符我们停止循环
Com(Broad,ROW,COL);
BroadDis(Broad, ROW, COL);
key=Is_win(Broad, ROW, COL);
if (key != 'N')
break;
}
//判断一下谁赢了
if (key == '#')
printf("玩家获胜\n");
else if (key == '*')
printf("电脑获胜\n");
else
printf("平局\n");
return;
}
再次良心的注释了一切。
写博客写道一半,突发奇想,拉着室友去外面骑小电驴逛街去了,溜达完回来写完博客已经凌晨一点了哈哈😂,家人们晚安。
尼尔叔叔:你自己试试做吧。
加油!!评论评论鼓励鼓励博主吧

(小福利)
前言一般来说,前端根据后台返回code码展示对应内容只需要在前台判断code值展示对应的内容即可,但要是匹配的code码比较多或者多个页面用到时,为了便于后期维护,后台就会使用字典表让前端匹配,下面我将在微信小程序中通过wxs的方法实现这个操作。为什么要使用wxs?{{method(a,b)}}可以看到,上述代码是一个调用方法传值的操作,在vue中很常见,多用于数据之间的转换,但由于微信小程序诸多限制的原因,你并不能优雅的这样操作,可能有人会说,为什么不用if判断实现呢?但是if判断的局限性在于如果存在数据量过大时,大量重复性操作和if判断会让你的代码显得异常冗余。wxswxs相当于是一个独立
项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU
@作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors 1、什么是behaviors 2、behaviors的工作方式 3、创建behavior 4、导入并使用behavior 5、behavior中所有可用的节点 6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors 1、什么是behaviorsbehaviors是小程序中,用于实现
我的Rails应用程序中安装了carrierwave。但是,当用户上传多页pdf时,我只希望应用程序获取文档中的第一页并将其转换为jpeg。这可能吗?用什么命令?这是我的uploader。#encoding:utf-8classImageUploader[200,300]##defscale(width,height)##dosomething#end#Createdifferentversionsofyouruploadedfiles:version:thumbdoprocess:resize_to_fill=>[150,210]process:convert=>:jpgdefful
有没有办法跳过CSV文件的第一行,让第二行作为标题?我有一个CSV文件,第一行是日期,第二行是标题,所以我需要能够在遍历它时跳过第一行。我尝试使用slice但它会将CSV转换为数组,我真的很想将其读取为CSV,以便我可以利用header。 最佳答案 根据您的数据,您可以使用另一种方法和skip_lines-option此示例跳过所有以#开头的行require'csv'CSV.parse(DATA.read,:col_sep=>';',:headers=>true,:skip_lines=>/^#/#Markcomments!)do|
我的任务是从数组中选择最高和最低的数字。我想我很清楚我想做什么,但只是努力以正确的格式访问信息以满足通过标准。defhigh_and_low(numbers)array=numbers.split("").map!{|x|x.to_i}array.sort!{|a,b|ba}putsarray[0,-1]end数字可能看起来像"80917234100",要通过,我需要输出"9234"。我正在尝试putsarray.first.last,但一直无法弄明白。 最佳答案 有Array#minmax完全满足您需要的方法:array=[80,
或者好像我必须自己写方法?(保持DHA不变):ruby-1.9.2-p180:001>s='omega-3(DHA)'=>"omega-3(DHA)"ruby-1.9.2-p180:002>s.capitalize=>"Omega-3(dha)"ruby-1.9.2-p180:003>s.titleize=>"Omega3(Dha)"ruby-1.9.2-p180:005>s[0].upcase+s[1..-1]=>"Omega-3(DHA)" 最佳答案 如果我的回答只是垃圾,我深表歉意(我不做ruby)。但我相信我已经为您找到了答
我有这个字符串:auteur="comtedeFlandreetHainaut,Baudouin,Jacques,Thierry"我想删除第一个逗号之前的所有内容,即在这种情况下保留“Baudouin,Jacques,Thierry”试过这个:nom=auteur.gsub(/.*,/,'')但这会删除最后一个逗号之前的每个逗号,只保留“Thierry”。 最佳答案 auteur.partition(",").last#=>"Baudouin,Jacques,Thierry" 关于rub
我有一个以时间戳为键的哈希。hash={"2016-05-31T22:30:58+02:00"=>{"path"=>"/","method"=>"GET"},"2016-05-31T22:31:23+02:00"=>{"path"=>"/tour","method"=>"GET"},"2016-05-31T22:31:05+02:00"=>{"path"=>"/contact_us","method"=>"GET"}}我订购了这个系列并得到了第一双这样的:hash.sort_by{|k,_|k}.first.first但是我该如何删除它呢?删除方法requiresyou知道key的准确
我有一个字符串数组,我需要从中提取第一个单词,将它们转换为整数并获得它们的总和。示例:["5Apple","5Orange","15Grapes"]预期输出=>25我的尝试:["5","5","15"].map(&:to_i).sum 最佳答案 我从你的问题中找到了答案。["5Apple","5Orange","15Grapes"].map(&:to_i).sum在数组中,如果存在任何整数可转换值,那么它将自动转换为整数。 关于arrays-字符串数组中字符串第一部分的总和,我们在Sta