C语言零基础项目:黑白棋游戏!详细思路+源码分享
haoteby 2025-04-27 13:46 38 浏览
每天一个C语言小项目,提升你的编程能力!
《黑白棋》也叫翻转棋或者奥赛罗,其游戏过程是相互翻转对方的棋子,最后以棋盘上谁的棋子多来判断胜负。虽然规则简单,但是变化复杂,是典型的易学难精,奥妙无穷,不信您就试试看吧!
游戏规则
轮到一方下棋时,必须把棋下在与对方棋子相邻的空位上,要求所下的棋子和原有的已方棋子夹住对方的至少一个棋子(横竖斜夹均可),然后把被夹住的子变成己方的颜色(也叫吃子)。下棋过程中,任何棋子既不会从棋盘上拿走,也不会从一个格子移到另一个格子。在轮到一方下棋时,如果该方无子可吃,就必须停一步,让对方继续下棋,这种情况叫pass;而当一方在有子可吃时,即使想pass也不允许pass 。
今天我们就用C语言来实现它!
由于项目包含很多图片,因此这里给出整个项目的压缩包:
https://codebus.cn/f/a/0/0/1/reversi.zip
以下是项目的全部源代码:
#include <graphics.h>
#include <cstdio>
#include <stdio.h>
/*******************************定义全局变量*****************************/
char map[8][8]; //棋盘
IMAGE img[6]; //保存图片
int black, white; //双方的棋子数
char today; //当前轮到谁走
/**********************************定义函数*****************************/
void load(void) //加载图片
{
loadimage(&img[0], "图片\\黑空.jpg");
loadimage(&img[1], "图片\\白空.jpg");
loadimage(&img[2], "图片\\黑子黑空.jpg");
loadimage(&img[3], "图片\\黑子白空.jpg");
loadimage(&img[4], "图片\\白子黑空.jpg");
loadimage(&img[5], "图片\\白子白空.jpg");
}
void print(void) //画棋盘
{
int x, y;
black = white = 0;
for(x = 0; x < 8; x++)
for(y = 0; y < 8; y++)
switch(map[x][y])
{
case 0:
if((x + y) % 2)
putimage(60 * y, 60 * x, &img[0]);
else
putimage(60 * y, 60 * x, &img[1]);
break;
case 'B':
if((x + y) % 2)
putimage(60 * y, 60 * x, &img[2]);
else
putimage(60 * y, 60 * x, &img[3]);
black++;
break;
case 'W':
if((x + y) % 2)
putimage(60 * y, 60 * x, &img[4]);
else
putimage(60 * y, 60 * x, &img[5]);
white++;
break;
}
}
inline void print1(void) //画当前谁走的
{
setcolor(WHITE);
bar(530, 60, 590, 120);
bar(530, 360, 590, 420);
if(today == 'B')
putimage(530, 60, &img[3]);
else
putimage(530, 360, &img[4]);
}
void draw(int x, int y, char a) //下当前子
{
char b = ((a == 'B') ? 'W' : 'B'); //敌方子
int x1, y1, x2, y2;
bool sign = false; //是否越过敌方子
for(x1 = x - 1; x1 >= 0 && map[x1][y]; x1--) //判断上方
{
if(map[x1][y] == b)
sign = true;
else
{
if(sign)
{
for(x2 = x - 1; x2 > x1; x2--) //判断下方
map[x2][y] = a;
}
break;
}
}
sign = false;
for(x1 = x + 1; x1 < 8 && map[x1][y]; x1++) //判断右方
{
if(map[x1][y] == b)
sign = true;
else
{
if(sign)
{
for(x2 = x + 1; x2 < x1; x2++)
map[x2][y] = a;
}
break;
}
}
sign = false;
for(y1 = y - 1; y1 >= 0 && map[x][y1]; y1--) //判断左方
{
if(map[x][y1] == b)
sign = true;
else
{
if(sign)
{
for(y2 = y - 1; y2 > y1; y2--)
map[x][y2] = a;
}
break;
}
}
sign = false;
for(y1 = y + 1; y1 < 8 && map[x][y1]; y1++) //判断右方
{
if(map[x][y1] == b)
sign = true;
else
{
if(sign)
{
for(y2 = y + 1; y2 < y1; y2++)
map[x][y2] = a;
}
break;
}
}
sign = false;
for(x1 = x - 1, y1 = y - 1; x1 >= 0 && y1 >= 0 && map[x1][y1]; x1--, y1--) //左上方
{
if(map[x1][y1] == b)
sign = true;
else
{
if(sign)
{
for(x2 = x - 1, y2 = y - 1; x2 > x1 && y2 > y1; x2--, y2--)
map[x2][y2] = a;
}
break;
}
}
sign = false;
for(x1 = x + 1, y1 = y + 1; x1 < 8 && y1 < 8 && map[x1][y1]; x1++, y1++) //右下方
{
if(map[x1][y1] == b)
sign = true;
else
{
if(sign)
{
for(x2 = x + 1, y2 = y + 1; x2 < x1 && y2 < y1; x2++, y2++)
map[x2][y2] = a;
}
break;
}
}
sign = false;
for(x1 = x + 1, y1 = y - 1; x1 < 8 && y1 >= 0 && map[x1][y1]; x1++, y1--) //左下方
{
if(map[x1][y1] == b)
sign = true;
else
{
if(sign)
{
for(x2 = x + 1, y2 = y - 1; x2 < x1 && y2 > y1; x2++, y2--)
map[x2][y2] = a;
}
break;
}
}
sign = false;
for(x1 = x - 1, y1 = y + 1; x1 >= 0 && y1 < 8 && map[x1][y1]; x1--, y1++) //右上方
{
if(map[x1][y1] == b)
sign = true;
else
{
if(sign)
{
for(x2 = x - 1, y2 = y + 1; x2 > x1 && y2 < y1; x2--, y2++)
map[x2][y2] = a;
}
break;
}
}
map[x][y] = a;
print();
}
bool judge(int x, int y, char a) //判断当前是否可以落下,同draw函数
{
char b = ((a == 'B') ? 'W' : 'B');
int x1, y1;
bool sign = false, sign1 = false; //sign1判断是否有效
if(map[x][y]) //如果当前不是空的返回假值
return false;
for(x1 = x - 1; x1 >= 0 && map[x1][y]; x1--)
{
if(map[x1][y] == b)
sign = true;
else
{
if(sign)
sign1 = true;
break;
}
}
sign = false;
for(x1 = x + 1; x1 < 8 && map[x1][y]; x1++)
{
if(map[x1][y] == b)
sign = true;
else
{
if(sign)
sign1 = true;
break;
}
}
sign = false;
for(y1 = y - 1; y1 >= 0 && map[x][y1]; y1--)
{
if(map[x][y1] == b)
sign = true;
else
{
if(sign)
sign1 = true;
break;
}
}
sign = false;
for(y1 = y + 1; y1 < 8 && map[x][y1]; y1++)
{
if(map[x][y1] == b)
sign = true;
else
{
if(sign)
sign1 = true;
break;
}
}
sign = false;
for(x1 = x - 1, y1 = y - 1; x1 >= 0 && y1 >= 0 && map[x1][y1]; x1--, y1--)
{
if(map[x1][y1] == b)
sign = true;
else
{
if(sign)
sign1 = true;
break;
}
}
sign = false;
for(x1 = x + 1, y1 = y + 1; x1 < 8 && y1 < 8 && map[x1][y1]; x1++, y1++)
{
if(map[x1][y1] == b)
sign = true;
else
{
if(sign)
sign1 = true;
break;
}
}
sign = false;
for(x1 = x + 1, y1 = y - 1; x1 < 8 && y1 >= 0 && map[x1][y1]; x1++, y1--)
{
if(map[x1][y1] == b)
sign = true;
else
{
if(sign)
sign1 = true;
break;
}
}
sign = false;
for(x1 = x - 1, y1 = y + 1; x1 >= 0 && y1 < 8 && map[x1][y1]; x1--, y1++)
{
if(map[x1][y1] == b)
sign = true;
else
{
if(sign)
sign1 = true;
break;
}
}
return sign1;
}
bool win(void) //判断是否有棋可走
{
int x, y;
for(x = 0; x < 8; x++)
for(y = 0; y < 8; y++)
if(judge(x, y, today))
return true;
return false;
}
bool quit(void) //判断是否有棋
{
int x, y;
bool b = false, w = false;
for(x = 0; x < 8; x++)
for(y = 0; y < 8; y++)
{
if(map[x][y] == 'B')
b = true;
else if(map[x][y] == 'W')
w = true;
}
return(b && w);
}
bool ask(void) //弹出对话框
{
HWND wnd = GetHWnd();
int key;
char str[30] = "黑:", s[2];
sprintf(s, "%d", black);
strcat(str, s);
strcat(str, " 白:");
sprintf(s, "%d", white);
strcat(str, s);
strcat(str, "\n是否重新开始?");
if(black == white)
key = MessageBox(wnd, str, "和局", MB_YESNO | MB_ICONQUESTION);
else if(black > white)
key = MessageBox(wnd, str, "黑胜", MB_YESNO | MB_ICONQUESTION);
else
key = MessageBox(wnd, str, "白胜", MB_YESNO | MB_ICONQUESTION);
if(key == IDYES)
return true;
else
return false;
}
void play(void) //游戏过程
{
MOUSEMSG m;
int x, y;
for(x = 0; x < 8; x++)
for(y = 0; y < 8; y++)
map[x][y] = 0;
map[3][4] = map[4][3] = 'B';
map[3][3] = map[4][4] = 'W';
today = 'B';
print();
print1();
do
{
do
{
while(true)
{
m = GetMouseMsg(); //获取鼠标消息
if(m.uMsg == WM_LBUTTONDOWN) //如果左键点击
break;
}
x = m.y / 60;
y = m.x / 60;
if(judge(x, y, today)) //如果当前位置有效
{
draw(x, y, today); //下子
today = ((today == 'B') ? 'W' : 'B');
print1(); //交换
}
}while(win() && quit()); //如果当前无棋可走
today = ((today == 'B') ? 'W' : 'B');
print1();
}while(win() && quit()); //双层判断
}
int main(void) //主函数
{
initgraph(640, 480);
load();
setbkcolor(WHITE);
cleardevice();
do
{
play();
}while(ask());
closegraph();
return 0;
}
大家赶紧去动手试试吧!
此外,我也给大家分享我收集的其他资源,从最零基础开始的教程到C语言C++项目案例,帮助大家在学习C语言的道路上披荆斩棘!
编程学习书籍分享:
编程学习视频分享:
整理分享(多年学习的源码、项目实战视频、项目笔记,基础入门教程)最重要的是你可以在群里面交流提问编程问题哦!
对于C/C++感兴趣可以关注小编在后台私信我:【编程交流】一起来学习哦!可以领取一些C/C++的项目学习视频资料哦!已经设置好了关键词自动回复,自动领取就好了!
相关推荐
- DIY桌面激光雕刻机#是时候展现真正的技术了
-
激光雕刻机。这期视频我们来看一下我是如何DIY一台桌面激光雕刻机。前几天在水池子边上发现了一台旧电脑,我看这电脑上还有一些东西可以利用到,比如光驱上面拆出了步进电机和滑轨。所以本期视频我将用这些废品去...
- 100000块多米诺骨牌拼成超级马里奥,这款机器人1天就完成了
-
智东西(公众号:zhidxcom)编译|王健恩编辑|高歌智东西7月30日消息,美国工程师兼YouTube博主MarkRober创造出了一个可以自动摆放多米诺骨牌的机器人。这个机器人被命名为D...
- 这个3D打印机器人可以在30秒内打开密码锁
-
密码锁看似很安全?也许曾经是,但现在你可要当心了!这是因为一台3D打印制造的机器人就可以在半分钟内打开你的密码锁。上周四,知名黑客萨米·卡姆卡尔(SamyKamkar)在自己的网站上公布了一个称之为...
- 密码锁也不安全 这款机器人30秒即可自动打开
-
大学生和体育爱好者们要注意了,千万不要再把贵重物品存放在公共储物柜里。因为现在已经出现了一种3D打印的机器人,据说世界上各大锁商推出的大部分密码锁,它都能够在30秒之内打开。著名黑客山米·卡姆卡(Sa...
- 硬件单片机模拟器,再也不用买开发板了...
-
#头条创作挑战赛#记得2006年在凌阳科技(sunplus)工作的时候,凌阳科技开发了自己的编译器/集成开发环境(unspIDE),那个IDE除了有keil那样的编辑器、编译器、链接器、调试器、下载...
- 3D打印机分哪几部分构成?(3d打印机结构组成及系统分析)
-
3D打印机的构成根据技术类型(如FDM、SLA、SLS等)有所不同,但以最常见的FDM(熔融沉积成型)3D打印机为例,其核心组成部分可分为以下模块:1.机械结构框架提供整体支撑和稳定性,常见材质为金...
- 初学者学伺服都需要什么?石家庄诺仕通
-
#初学者学伺服都需要什么?#对于初学者学习伺服系统,需要从...
- arduino(arduino是单片机吗)
-
arduino学习笔记arduino学习笔记1-什么是arduino?...
- 自制写字机,你需要的全套资料都在这里
-
小编之前发过《用废旧光驱制作迷你绘图仪》,很多读者都成功制作了自己的绘图仪。但是该方法的缺点是gcode要在inkscape软件中生成,然后通过grbl-controller这个没有界面的程序发送画图...
- 自己动手DIY3D打印机 瞬间效果出现桌面时,大家都惊呆了!
-
3D打印机,对数码产品比较了解的朋友都知道,但是真正玩过的童鞋可能就不多了。其实3D打印机离我们并不远,随着3D打印技术越来越成熟,3D打印机的学习资料也越来越多,这让自己动手做一台桌面3D打印机也成...
- 机器人仅用24小时将十万块多米诺骨牌拼出马里奥,创下世界纪录
-
十万块多米诺骨牌倒下是个啥场面?等等,十万块?那得搭多久啊?...
- 如何制作一个机器人?(制作机器人的方法)
-
1.简单机械机器人(例如自动小车)2.智能机器人(带有人工智能或计算机视觉)3.工业机器人(用于生产自动化)4.人形机器人(类人结构,可以行走、对话)...
- CrowPi2树莓派4学习套件评测第1部分–开箱和首次启动
-
文章来源:CNXSoftware中文站2020年6月,我曾写过一篇关于深圳易科诺...
- 基于 Arduino UNO 的蓝牙汽车(arduino智能小车蓝牙控制app)
-
HC-05蓝牙模块HC-05是一款易于使用的蓝牙SPP模块,针对流畅的串行无线通信配置进行了优化。串口蓝牙模块是完全合格的蓝牙V2.0+EDR(增强数据速率)3Mbps调制,具有总2.4...
- 电机驱动设计方案带你初识机电一体化
-
在直流电机驱动电路的设计中,主要考虑以下几点:功能:电机是单向还是双向转动?需不需要调速?...