2021-06-10

c语言实现五子棋游戏

#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)
//书写头文件
#include <stdio.h>   
#include <windows.h>   //该头文件分装了许多库函数以及一些类,将一些复杂的工作由库函数处理涉及到图形界面接口,图形设备函数很多重要功能
#include <time.h>      //用于需要时间方面的函数
#include <conio.h>     //定义了控制台进行数据输入和输出的函数
#include <stdlib.h>
#define N 65

   //定义变量
int status[N][N] = { {0},{0} };//记录棋盘情况,0无,1红棋/玩家,2为白棋/电脑 ,status一般写程序时会定义这样一个类型用来表示成功或失败状态
int flag = 0;//判断输赢 ;flag一般用来标记,记录的标志变量
int direct[2];//方向
int Value1[N][N] = { {0},{0} };//计算权值 
int Value2[N][N] = { {0},{0} };//计算权值
int regrex, regrey, regrex1, regrey1;
int count = 0;//计算棋子数量 

void chess_board();//打印棋盘 
void red_movexy();//红子棋移动光标
void white_movexy();//白棋移动光标 
void red_chess(int x, int y);//红棋坐标
void white_chess(int x, int y);//白棋坐标
void man_man();  //人人对战
void man_machine();//人机对战
int judge_chess(int x, int y);//判断这个位置是否下过 
int judge_winner(int x, int y, int temp);//判断输赢 
void machine_attack();//电脑进攻权值 
void machine_defend();//电脑防守权值 
void find_position();//寻找最佳权值
void Regret();//悔棋函数 

void BackGround(unsigned int ForeColor, unsigned int BackGroundColor)  //颜色 ;unsigned  int是无符号整数的意思,无符号整型只有0和正数
{
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);  //获取控制台的句柄 ;GetStdHandle该函数用于取得指定的标准设备的句柄。HANDLE  是无类型指针(不指向任何类型数据的指针)
	//,句柄是处理对象的一个接口,可以通过句柄去操作程序中所涉及的对象。
	
	SetConsoleTextAttribute(handle, ForeColor + BackGroundColor * 0x10);//改变当前光标的背景和字体颜色;利用SetConsoleTextAttribute函数改变控制台输出字体颜色
}

void gotoxy(int x, int y)    //光标函数 
{
	HANDLE handle;
	COORD coord;   //获取坐标轴结构体,coord表示文字在控制台的坐标
	coord.X = x;   //给x轴赋值
	coord.Y = y;   //给y轴赋值
	handle = GetStdHandle(STD_OUTPUT_HANDLE);  //获取控制台句柄,值为-11
	SetConsoleCursorPosition(handle, coord);   //移动光标到x,y处,SetConsoleCursorPosition光标的位置设置和控制台字体颜色的控制
}

void chess_board()//打印棋盘 
{
	int i, j;
	for (i = 0; i <= 30; i++)
		for (j = 0; j <= 60; j += 4)
		{
			gotoxy(j, i);
			printf("|");
		}
	for (i = 0; i <= 30; i += 2)
		for (j = 1; j <= 57; j += 4)
		{
			gotoxy(j, i);
			printf("---");
		}
}

void chess_menu()//打印棋盘旁的菜单 
{
	int i, j;
	for (i = 1; i <= 29; i++)
	{
		gotoxy(67, i);
		printf("||");
	}
	for (i = 1; i <= 29; i++)
	{
		gotoxy(89, i);
		printf("||");
	}
	gotoxy(69, 1);
	printf("--------------------");
	gotoxy(69, 29);
	printf("--------------------");
	gotoxy(75, 3);
	printf("模   式");
	gotoxy(75, 20);
	printf("提   示");
}

void red_movexy()//红棋移动光标 
{
loop2:gotoxy(direct[0], direct[1]);
	char key = 'y';
	int temp;
	while (key != ' ')
	{
		key = getch();
		switch (key)
		{
		case 'W':    //按w键向上
		case 'w':
			direct[1] -= 2;
			if (direct[1] <= 1)
				direct[1] = 1;
			break;
		case 's':    //按s键向下
		case 'S':
			direct[1] += 2;
			if (direct[1] >= 29)
				direct[1] = 29;
			break;
		case 'a':   //按a向左
		case 'A':
			direct[0] -= 4;
			if (direct[0] <= 2)
				direct[0] = 2;
			break;
		case 'd':   //按d向右
		case 'D':
			direct[0] += 4;
			if (direct[0] >= 58)
				direct[0] = 58;
			break;
		case 'q':
		case 'Q':  //按q悔棋
		{
			int message = MessageBox(NULL, "是否确定悔棋?", "友情提示", MB_OKCANCEL);  //MessageBox它的功能是弹出一个标准的Windows对话框
			if (IDCANCEL == message)      //取消悔棋
				break;
			if (IDOK == message)          //确定悔棋
			{
				Regret();
				break;
			}
		}
		}
		gotoxy(direct[0], direct[1]); //将光标移动到指定的位置
	}
	temp = judge_chess(direct[1], direct[0]);  //判断位置是否被下过
	if (temp == 1)
	{
		gotoxy(70, 22);
		BackGround(4, 0);
		printf("这里已经被人下过了");
		goto loop2;
	}
}

void white_movexy()//白棋移动光标 (白棋为电脑或对手)
{
loop1:gotoxy(direct[0], direct[1]);
	char key = 'y';
	int temp;
	while (key != '0')
	{
		key = getch();
		switch (key)
		{
		case 72:
			direct[1] -= 2;
			if (direct[1] <= 1)
				direct[1] = 1;
			break;
		case 80:
			direct[1] += 2;
			if (direct[1] >= 29)
				direct[1] = 29;
			break;
		case 75:
			direct[0] -= 4;
			if (direct[0] <= 2)
				direct[0] = 2;
			break;
		case 77:
			direct[0] += 4;
			if (direct[0] >= 58)
				direct[0] = 58;
			break;
		case 'B':
		case 'b':
		{
			int message = MessageBox(NULL, "是否确定悔棋?", "友情提示", MB_OKCANCEL);
			if (IDCANCEL == message)
				break;
			if (IDOK == message)
			{
				Regret();
				break;
			}
		}
		}
		gotoxy(direct[0], direct[1]);
	}
	temp = judge_chess(direct[1], direct[0]);//判断是否下过棋
	if (temp == 1)
	{
		gotoxy(70, 22);
		BackGround(4, 0);
		printf("这里已经被人下过了");
		goto loop1;
	}
}

void red_chess(int x, int y)//打印红棋 
{
	BackGround(4, 0);
	regrex = x;//记录上一落子的位置 ,方便悔棋 
	regrey = y;
	count++;
	printf("●");
	status[x][y] = 1;
}

void white_chess(int x, int y)//打印白棋
{
	BackGround(7, 0);
	regrex1 = x;
	regrey1 = y;
	printf("●");
	count++;
	status[x][y] = 2;
}

void machine_chess(int x, int y)//电脑落子
{
	BackGround(7, 0);
	status[x][y] = 2;
	regrex1 = x;
	regrey1 = y;
	count++;
	gotoxy(y, x);
	printf("●");
}

int judge_chess(int x, int y)//判断这个地方是否有棋子
{
	if (status[x][y] == 0)
		return 0;
	else
		return 1;
}

int judge_winner(int x, int y, int temp)//判断输赢 
{
	int i, j, n1, n2;
	n1 = n2 = 0;
	for (i = x, j = y + 4; j <= 58; j += 4)//向右寻找棋子数
	{
		if (status[i][j] == temp)
			n1++;
		else
			break;
	}
	for (i = x, j = y; j >= 2; j -= 4)//向左寻找棋子数
	{
		if (status[i][j] == temp)
			n2++;
		else
			break;
	}
	if (n1 + n2 >= 5)
		return temp;
	n1 = n2 = 0;
	for (i = x, j = y; i >= 1; i -= 2)//向上寻找棋子数
	{
		if (status[i][j] == temp)
			n1++;
		else
			break;
	}
	for (i = x + 2, j = y; i <= 30; i += 2)//向下寻找棋子数 
	{
		if (status[i][j] == temp)
			n2++;
		else
			break;
	}
	if (n1 + n2 >= 5)
		return temp;
	n1 = n2 = 0;
	for (i = x - 2, j = y + 4; i >= 1 && j <= 58; i -= 2, j += 4)//向右上寻找棋子数
	{
		if (status[i][j] == temp)
			n1++;
		else
			break;
	}
	for (i = x, j = y; i <= 30 && j >= 2; i += 2, j -= 4)//向左下寻找棋子数
	{
		if (status[i][j] == temp)
			n2++;
		else
			break;
	}
	if (n1 + n2 >= 5)
		return temp;
	n1 = n2 = 0;
	for (i = x, j = y; i >= 0 && j >= 0; i -= 2, j -= 4)//向左上寻找棋子数 
	{
		if (status[i][j] == temp)
			n1++;
		else
			break;
	}
	for (i = x + 2, j = y + 4; i <= 30 && j <= 58; i += 2, j += 4)//向右下寻找棋子数
	{
		if (status[i][j] == temp)
			n2++;
		else
			break;
	}
	if (n1 + n2 >= 5)
		return temp;
	return 0;
}

void machine_attack()//电脑进攻权值 
{
	int i1, j1;
	int k1, k2, k;
	for (int i = 1; i <= 30; i += 2)
	{
		for (int j = 2; j <= 58; j += 4)
		{
			if (status[i][j])
				Value1[i][j] = 0;
			if (status[i][j] == 0)
			{
				k1 = k2 = 0;
				for (i1 = i, j1 = j - 4; j1 >= 2; j1 -= 4)//往左数寻找电脑棋子数
				{
					if (status[i1][j1] == 2)
						k1++;
					else
						break;
				}
				for (i1 = i, j1 = j + 4; j1 <= 58; j1 += 4)//往右数寻找电脑棋子数
				{
					if (status[i1][j1] == 2)
						k2++;
					else
						break;
				}
				k = k1 > k2 ? k1 : k2;
				k1 = k2 = 0;
				for (i1 = i - 2, j1 = j; i1 >= 1; i1 -= 2)//往上数寻找电脑棋子数
				{
					if (status[i1][j1] == 2)
						k1++;
					else
						break;
				}
				for (i1 = i + 2, j1 = j; i1 <= 30; i1 += 2)//往下数寻找电脑棋子数
				{
					if (status[i1][j1] == 2)
						k2++;
					else
						break;
				}
				k1 = k1 > k2 ? k1 : k2;
				k = k > k1 ? k : k1;
				k1 = k2 = 0;
				for (i1 = i - 2, j1 = j - 4; i1 >= 0 && j1 >= 0; i1 -= 2, j1 -= 4)//往左上数寻找电脑棋子数
				{
					if (status[i1][j1] == 2)
						k1++;
					else
						break;
				}
				for (i1 = i + 2, j1 = j + 4; i1 <= 30 && j1 <= 58; i1 += 2, j1 += 4)//往右下数寻找电脑棋子数
				{
					if (status[i1][j1] == 2)
						k2++;
					else
						break;
				}
				k1 = k1 > k2 ? k1 : k2;
				k = k > k1 ? k : k1;
				k1 = k2 = 0;
				for (i1 = i + 2, j1 = j - 4; i1 <= 30 && j1 >= 2; i1 += 2, j1 -= 4)//往左下数寻找电脑棋子数
				{
					if (status[i1][j1] == 2)
						k1++;
					else
						break;
				}
				for (i1 = i - 2, j1 = j + 4; i1 >= 1 && j1 <= 58; i1 -= 2, j1 += 4)//往右上数寻找电脑棋子数
				{
					if (status[i1][j1] == 2)
						k2++;
					else
						break;
				}
				k1 = k1 > k2 ? k1 : k2;
				k = k > k1 ? k : k1;
				switch (k)
				{
				case 3:
					Value1[i][j] = 15; break;
				case 4:
					Value1[i][j] = 25; break;
				default:
					Value1[i][j] = 3 + 2 * k; break;
				}
			}
		}
	}
}

void machine_defend()//防守权值
{
	int i1, j1;
	int k1, k2, k;
	for (int i = 1; i <= 30; i += 2)
	{
		for (int j = 2; j <= 58; j += 4)
		{
			if (status[i][j])
				Value2[i][j] = 0;
			if (status[i][j] == 0)
			{
				k1 = k2 = 0;
				for (i1 = i, j1 = j - 4; j1 >= 2; j1 -= 4)//往左数寻找玩家棋子数
				{
					if (status[i1][j1] == 1)
						k1++;
					else
						break;
				}
				for (i1 = i, j1 = j + 4; j1 <= 58; j1 += 4)//往右数寻找玩家棋子数
				{
					if (status[i1][j1] == 1)
						k2++;
					else
						break;
				}
				k = k1 > k2 ? k1 : k2;
				k1 = k2 = 0;
				for (i1 = i - 2, j1 = j; i1 >= 1; i1 -= 2)//往上数寻找玩家棋子数
				{
					if (status[i1][j1] == 1)
						k1++;
					else
						break;
				}
				for (i1 = i + 2, j1 = j; i1 <= 30; i1 += 2)//往下数寻找玩家棋子数
				{
					if (status[i1][j1] == 1)
						k2++;
					else
						break;
				}
				k1 = k1 > k2 ? k1 : k2;
				k = k > k1 ? k : k1;
				k1 = k2 = 0;
				for (i1 = i - 2, j1 = j - 4; i1 >= 1 && j1 >= 2; i1 -= 2, j1 -= 4)//往左上数寻找玩家棋子数
				{
					if (status[i1][j1] == 1)
						k1++;
					else
						break;
				}
				for (i1 = i + 2, j1 = j + 4; i1 <= 30 && j1 <= 58; i1 += 2, j1 += 4)//往右下数寻找玩家棋子数
				{
					if (status[i1][j1] == 1)
						k2++;
					else
						break;
				}
				k1 = k1 > k2 ? k1 : k2;
				k = k > k1 ? k : k1;
				k1 = k2 = 0;
				for (i1 = i + 2, j1 = j - 4; i1 <= 30 && j1 >= 2; i1 += 2, j1 -= 4)//往左下数寻找玩家棋子数
				{
					if (status[i1][j1] == 1)
						k1++;
					else
						break;
				}
				for (i1 = i - 2, j1 = j + 4; i1 >= 1 && j1 <= 58; i1 -= 2, j1 += 4)//往右上数寻找玩家棋子数
				{
					if (status[i1][j1] == 1)
						k2++;
					else
						break;
				}
				k1 = k1 > k2 ? k1 : k2;
				k = k > k1 ? k : k1;
				switch (k)
				{
				case 3:
					Value2[i][j] = 10; break;
				case 4:
					Value2[i][j] = 20; break;
				default:
					Value2[i][j] = 2 + k * 2;
				}
			}
		}
	}
}

void find_position()//找到最有价值的位置
{
	int k1 = 0, k2 = 0;
	int i, j, max = 0;
	for (i = 1; i <= 30; i += 2)
		for (j = 2; j <= 58; j += 4)
		{
			if (max <= Value1[i][j])
			{
				max = Value1[i][j];
				k1 = i;
				k2 = j;
			}
		}
	for (i = 1; i <= 30; i += 2)
		for (j = 2; j <= 58; j += 4)
		{
			if (max <= Value2[i][j])
			{
				max = Value2[i][j];
				k1 = i;
				k2 = j;
			}
		}
	direct[1] = k1;  //将找到的位置传给光标
	direct[0] = k2;
}

void man_man()//人人对战模式
{
loop5:system("cls");
	char key;
	int control;
	gotoxy(2, 3);
	printf("1.红 子 先 手");

	gotoxy(2, 5);
	printf("2.白 子 先 手");

	gotoxy(2, 7);
	printf("(输入相应序号选择)");
	key = getch();
	system("cls");
	if (key == '1')
		control = 1;
	else if (key == '2')
		control = -1;
	else
		goto loop5;
	gotoxy(70, 5);
	printf("   人 人 对 战    ");
	direct[1] = 15;
	direct[0] = 30;
	chess_board();
	chess_menu();
	while (flag == 0)
	{
		if (control == 1)
		{
			gotoxy(70, 22);
			BackGround(6, 0);
			printf("   红 子 执 手    ");
			red_movexy();
			red_chess(direct[1], direct[0]);
			flag = judge_winner(direct[1], direct[0], 1);
		}
		else
		{
			gotoxy(70, 22);
			BackGround(6, 0);
			printf("   白 子 执 手    ");
			white_movexy();
			white_chess(direct[1], direct[0]);
			flag = judge_winner(direct[1], direct[0], 2);
		}
		control = -control;
	}
	if (flag == 1)
	{
		BackGround(7, 0);
		MessageBox(NULL, "游戏结束,红子胜利", "五子棋游戏", MB_OK);
	}
	if (flag == 2)
	{
		MessageBox(NULL, "游戏结束,白子胜利", "五子棋游戏", MB_OK);
	}
	if (count >= 225)
	{
		MessageBox(NULL, "游戏结束,平局", "五子棋游戏", MB_OK);
	}
}

void man_machine()//人机对战模式 
{
loop6:system("cls");
	char key;
	int control;
	gotoxy(2, 3);
	printf("1.玩 家 先 手(玩家为红子)");

	gotoxy(2, 5);
	printf("2.电 脑 先 手(电脑为白子)");

	gotoxy(2, 7);
	printf("(输入相应序号选择)");
	key = getch();
	system("cls");
	if (key == '1')
		control = 1;
	else if (key == '2')
	{
		control = 1;
		machine_chess(13, 26);
	}
	else
		goto loop6;
	gotoxy(70, 5);
	printf("   人 机 对 战    ");
	direct[1] = 15;
	direct[0] = 30;
	chess_board();
	chess_menu();
	while (flag == 0)
	{
		if (control == 1)
		{
			gotoxy(70, 22);
			BackGround(6, 0);
			printf("   玩 家 执 手    ");
			red_movexy();
			red_chess(direct[1], direct[0]);
			flag = judge_winner(direct[1], direct[0], 1);
		}
		else
		{
			gotoxy(70, 22);
			BackGround(6, 0);
			printf("   电 脑 执 手    ");
			machine_defend();
			machine_attack();
			find_position();
			machine_chess(direct[1], direct[0]);
			flag = judge_winner(direct[1], direct[0], 2);
		}
		control = -control;
	}
	gotoxy(8, 18);
	if (flag == 1)
	{
		BackGround(7, 0);
		MessageBox(NULL, "太厉害了,您竟然战胜了电脑!", "五子棋游戏", MB_OK);
	}
	if (flag == 2)
	{
		MessageBox(NULL, "游戏结束,您输给了电脑", "五子棋游戏", MB_OK);
	}
	if (count >= 225)
	{
		MessageBox(NULL, "平局", "五子棋游戏", MB_OK);
	}
}

void Regret()//悔棋函数 
{
	gotoxy(regrey, regrex);
	BackGround(0, 0);
	printf(" ");
	status[regrex][regrey] = 0;
	gotoxy(regrey1, regrex1);
	BackGround(0, 0);
	printf(" ");
	status[regrex1][regrey1] = 0;
	count -= 2;
}

void welcome()//游戏菜单 
{
	int k;
	char choose;
	system("cls");
	for (k = 2; k <= 16; k += 2)//游戏菜单 
	{
		gotoxy(5, k);
		printf("|-----------------|");
	}
	gotoxy(5, 3);
	printf("|  五 子 棋 游 戏 |");

	gotoxy(5, 5);
	printf("|     菜    单    |");

	gotoxy(5, 7);
	printf("|  1.人 人 对 战  |");

	gotoxy(5, 9);
	printf("|  2.人 机 对 战  |");

	gotoxy(5, 11);
	printf("|  3.游 戏 帮 助  |");

	gotoxy(5, 13);
	printf("|  4.更 新 日 志  |");

	gotoxy(5, 15);
	printf("|  5.退 出 游 戏  |");

	gotoxy(5, 18);
	printf("温馨提示:输入菜单对应序号进行操作");

	gotoxy(5, 20);
	printf("祝您游戏愉快!");

	gotoxy(13, 20);
}

char Gametips()//游戏帮助 
{
	char choose;
	int key;

	system("cls");

	gotoxy(2, 3);
	printf("游戏操作:");

	gotoxy(4, 5);
	printf("① 红色棋子WASD移动光标选择下棋位置,按空格键确认,按Q悔棋");

	gotoxy(4, 7);
	printf("② 白色棋子↑↓←→移动光标选择下棋位置,按0确认,按B悔棋");

	gotoxy(2, 19);
	printf("(按E键返回,按其它任意键退出)");

	return getch();
}

char Updatediary()//更新日志 
{
	system("cls");

	gotoxy(2, 3);
	printf("(暂时没有)");

	gotoxy(2, 5);
	printf("(按E键返回,按其它任意键退出)");

	return getch();
}

int main()
{
	system("title 五子棋");
	system("mode con cols=92 lines=33");
	char choose, temp;
loop:welcome();
	choose = getch();
	switch (choose)
	{
	case '1':
		man_man();
		break;
	case '2':
		man_machine();
		break;
	case '3':
		temp = Gametips();
		if (temp == 'E' || temp == 'e')
			goto loop;
		break;
	case '4':
		temp = Updatediary();
		if (temp == 'E' || temp == 'e')
			goto loop;
		break;
	case '5':
		int message = MessageBox(NULL, "是否退出?", "友情提示", MB_OKCANCEL);
		if (IDCANCEL == message)
			goto loop;
		if (IDOK == message)
		{
			break;
		}
	}
}

运行不了代码可能是以下情况
const.char类型形参与LPWSTR类型的实参不兼容:)
具体处理方法可以在这里插入图片描述点击工具 再点击属性 在最后在常规中找到字符集 把它改为常字符集就🆗了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值