八,五子棋游戏
程序应用C语言编写程序,可以在计算机上实现二人对弈五子棋功能。
功能要求:
(1)欢迎界面生成、游戏界面生成;
(2)光标移动和落子显示;
(3)判断胜负、悔棋功能,提供音效;
(4)综合应用结构体、数组、按键处理和图形编程等编程方法。
#include <stdio.h>
#include<windows.h>
#include <stdlib.h>
#include<conio.h>
int s;
int winner;
int player;
int Q[200][200] = { 0 };
char button;
struct Point
{
int x;
int y;
} point, game;
struct Pieces
{
struct Point coord;
struct Pieces *fore;
};
struct Pieces *p, *ptr, *ptr1, *head;
void goto_xy(int x, int);
void init();
void welcome();
void showwho();
void draw();
void clean();
void menu(char press);
void go_back(int x1, int y1);
void record();
void putdown();
void play(char ch);
int judge();
int main();
void goto_xy(int x, int y) //光标移动函数
{
COORD c;
c.X = 2 * x;
c.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
//使光标 到(x,y)位置的函数//调用 COORD 需要#include<windows.h>.
}
void init()//初始化函数,将记录棋子的数组初始化
{
for (int i = 0; i < 200; i++)
for (int j = 0; j < 200; j++)
Q[i][j] = 0;
s = 0;
player = 1;
p = (struct Pieces *)malloc(sizeof(struct Pieces));
// 动态声明了一个pieces结构体的内存空间, 并将这块空间的指针保存给p变量
head = p;
}
void welcome()
{
system("color 2F");
goto_xy(17, 1);
printf("\n\t\t*****************欢迎来到五子棋小游戏******************\n");
goto_xy(13, 3);
printf("\n\t\t\t********主菜单***********\n");
goto_xy(13, 4);
printf("\n\t\t\t\t***人人对战***\n");
printf("\n\t\t\t\t\t退出");
point.x = 12;
point.y = 3;
goto_xy(0, 0);
}
void showwho()
{
goto_xy(17, 22);
if (player == 0)
printf("轮到甲方落子");
else
printf("轮到乙方落子");
goto_xy(point.x, point.y);
}
void draw()
{
game.x = 10;
game.y = 3;
system("cls");
system("color 3F");
goto_xy(15, 1);
printf("欢迎进入五子棋小游戏!!\n");
goto_xy(29, 22);
printf("重新开始请输入r\n");
goto_xy(1, 22);
printf("悔棋请输入b\n");
goto_xy(1, 23);
printf("退出请按ESC\n");
const int i = 8; //const 定义的数据不可以被改变 而且修改数据比较方便
const int j = 19;
const int k = 3;
goto_xy(game.x - i, game.y + k); //甲光标的初始化位置
printf("甲方:●\n");
goto_xy(game.x - i, game.y + k + 2);
printf("向上移动:↑\n");
goto_xy(game.x - i, game.y + k + 4);
printf("向下移动:↓\n");
goto_xy(game.x - i, game.y + k + 6);
printf("向左移动:←\n");
goto_xy(game.x - i, game.y + k + 8);
printf("向右移动:→\n");
goto_xy(game.x - i, game.y + k + 10);
printf("落子: Enter\n");
goto_xy(game.x + j, game.y + k);
printf("乙方:○\n");
goto_xy(game.x + j, game.y + k + 2);
printf("向上移动:↑\n");
goto_xy(game.x + j, game.y + k + 4);
printf("向下移动:↓\n");
goto_xy(game.x + j, game.y + k + 6);
printf("向左移动:←\n");
goto_xy(game.x + j, game.y + k + 8);
printf("向右移动:→\n");
goto_xy(game.x + j, game.y + k + 10);
printf("落子: Enter\n");
for (int k1 = 0; k1 < 200; k1++)
//初始化棋子记录,在第二局时有明确的作用
for (int k2 = 0; k2 < 200; k2++)
Q[k1][k2] = 0;
for (int i = 0; i < 18; i++)
{
if (i == 0)
{
goto_xy(10, i + 3);
printf("┌┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┐");
}
if (i != 0 && i != 17)
{
goto_xy(10, i + 3);
printf("├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤");
}
if (i == 17)
{
goto_xy(10, i + 3);
printf("└┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┘");
}
}
point.x = 19;
point.y = 12;
goto_xy(19, 12);
}
void clean()
{
goto_xy(10, 3);
printf(" ");
goto_xy(24, 3);
printf(" ");
goto_xy(10, 4);
printf(" ");
goto_xy(24, 4);
printf(" ");
}
void menu(char press)
{
if (press == 72) //↑的ASCLL码
{
if (point.y == 3)
point.y = 4;
else
point.y = 3;
clean();
goto_xy(10, point.y);
printf("—→");
}
if (press == 80) //↓的ASCLL码
{
if (point.y == 4)
point.y = 3;
else
point.y = 4;
clean();
goto_xy(10, point.y);
printf("—→");
}
if (press == 13) // 13:回车键的ASCLL码
{
s = point.y - 2; //s 为1或2
}
}
void go_back(int x1, int y1) //悔棋函数
{
goto_xy(x1, y1);
if (x1 == 10)
{
if (y1 == 3)
{
printf("┌");
}
else
if (y1 == 20)
{
printf("└");
}
else
{
printf("├");
}
}
else if (x1 == 27)
{
if (y1 == 3)
{
printf("┐");
}
else
if (y1 == 20)
{
printf("┘");
}
else
{
printf("┤");
}
}
else
{
if (y1 == 3)
{
printf("┬");
}
else
if (y1 == 20)
{
printf("┴");
}
else
{
printf("┼");
}
}
Q[point.x][point.y] = 0;
goto_xy(x1, y1);
}
void record() //记录棋子的情况
{
p->coord.x = point.x;
p->coord.y = point.y;
ptr = p;
p = (struct Pieces *)malloc(sizeof(struct Pieces));
p->fore = ptr;
showwho();
Q[point.x][point.y] = player + 1;
if (player)
{
player = 0;
return;
}
player = 1;
goto_xy(point.x, point.y);
}
void putdown()
{
if (Q[point.x][point.y] == 0) //先判断该位置是否有棋子
{
if (player)
{
printf("●");
printf("\a"); //'\a'表示蜂鸣声
record();
}
else
{
printf("○");
printf("\a");
record();
}
goto_xy(point.x, point.y);
}
}
void play(char ch)
{
if (ch == 72)
{
if (point.y <= 3)
point.y = 20;
else
point.y--;
goto_xy(point.x, point.y);
}
if (ch == 75) //←的ASCLL码 光标左移
{
if (point.x <= 10)
point.x = 27;
else
point.x--;
goto_xy(point.x, point.y);
}
if (ch == 77) //→的ASCLL码 光标右移
{
if (point.x >= 27)
point.x = 10;
else
point.x++;
goto_xy(point.x, point.y);
}
if (ch == 80) //↓的ASCLL码 光标下移
{
if (point.y >= 20)
point.y = 3;
else
point.y++;
goto_xy(point.x, point.y);
}
if (ch == 13) //回车键的ASCLL码 下棋
{
putdown();
}
if (button == 'b' || button == 'B') //悔棋的操作
{
ptr1 = p;
if (p != head)
{
p = p->fore;
free(ptr1);
point.x = p->coord.x;
point.y = p->coord.y;
go_back(point.x, point.y);
}
}
}
int judge()
{
int count = 0;
int pp = player == 0 ? 2 : 1;
int c = 0;
int r = 0;
int rr = r;
int cc = c;
for (c = 0; c < 200; c++)
{
for (r = 0; r < 200; r++)
{
if (Q[r][c] != pp)
continue;
while (--cc >= 3 && Q[rr][cc] == pp)
count++;
cc = c;
while (++cc < 23 && Q[rr][cc] == pp)
count++;
cc = c;
if (count >= 4)
return pp;
count = 0;
while (--rr >= 10 && Q[rr][cc] == pp)
count++;
rr = r;
while (++rr < 30 && Q[rr][cc] == pp)
count++;
rr = r;
if (count >= 4)
return pp;
count = 0;
cc--;
rr--;
while ((cc >= 3 || rr >= 10) && Q[rr][cc] == pp)
{
count++;
cc--;
rr--;
}
rr = r;
cc = c;
cc++;
rr++;
while ((cc < 23 || rr < 30) && Q[rr][cc] == pp)
{
count++;
cc++;
rr++;
}
rr = r;
cc = c;
if (count + 1 >= 5)
return pp;
count = 0;
cc++;
rr--;
while ((cc < 23 || rr >= 10) && Q[rr][cc] == pp)
{
count++;
cc++;
rr--;
}
rr = r;
cc = c;
cc--;
rr++;
while ((cc >= 3 || rr < 30) && Q[rr][cc] == pp)
{
count++;
cc--;
rr++;
}
rr = r;
cc = c;
if (count + 1 >= 5)
return pp;
count = 0;
}
} return 0;
}
int main(void)
{
system("color 4E");
printf("\n欢迎来到五子棋小游戏\n");
welcome();
Sleep(3000);
system("cls");
while (1)
{
init();
int winner = 0;
welcome();
while (1) //读取菜单选项
{
char choice = getch();
menu(choice);
if (s != 0)
break;
}
if (s == 1) //选择人人对战
{
draw();
goto_xy(17, 22);
printf("轮到甲方落子");
goto_xy(point.x, point.y);
while (1)
{
button = getch();
play(button);
if (button == 27) //ESC的ASCLL码
{
if (MessageBox(NULL, TEXT("确定退出?"), TEXT(""), MB_ICONQUESTION | MB_OKCANCEL) == IDOK)
{
system("cls");
printf("\n 谢谢使用!\n");
return 0;
}
}
if (button == 13) //回车键ASCLL码 开始判断输赢
winner = judge();
if (winner != 0)
{
goto_xy(15, 24);
if (winner == 2)
{
printf("恭喜!甲方赢!\n");
}
if (winner == 1)
{
printf("恭喜!乙方赢!\n");
}
}
if (winner != 1 && winner != 2)
{
continue;
}
goto_xy(13, 22);
printf(" 继续游戏?(Y/N): ");
while (1)
{
button = getch();
if (button == 'n' || button == 'N' || button == 'y' || button == 'Y')
break;
}
if (button == 'n' || button == 'N')
{
if (MessageBox(NULL, TEXT(" 确定退出"), TEXT(""), MB_ICONQUESTION | MB_OKCANCEL) == IDOK)
{
system("cls");
printf("\n 谢谢使用!\n");
return 0;
}
}
if (button == 'y' || button == 'Y')
{
winner = 0;
system("cls");
break;
}
}
}
if (s == 2)
{
if (MessageBox(NULL, TEXT(" 确定"), TEXT(""), MB_ICONQUESTION | MB_OKCANCEL) == IDOK)
{
printf("\n\n 谢谢使用!\n");
return 0;
}
}
}
return 0;
}
不足之处,请多指教!!