C#-wpf一个简单的井字棋程序
来源:互联网 发布:网络催生新职业 编辑:程序博客网 时间:2024/06/04 17:59
前言
好久没有碰过代码了,上次看C#估计还是上个学期233,这次老师突然布置了一个C#语言编写的井字棋程序让我有点措手不及.不过,仗着微软爸爸的vs的强大的代码补全能力,最后还是将这个程序做好了(遇到了很多坑).
要求
该程序的要求还是有点多了,以下一一列举:
1. 在程序初始化时,要求输入玩家用户名,输入后出现提示文字,并选择是先手还是后手.
2. 点击Fight!后,进入游戏界面,在九宫格中下一步棋后,电脑(敌人)会判断形势并下第二部棋,如此直至有三子连成一线(玩家或电脑赢),或者格子被占满(和局).旁边有提示按钮,点击后会出现提示;得分按钮会出现具体的得分界面;退出按钮则会退出程序
3. 得分界面,点开后会显示自己的得分情况.最高得分按钮会记录玩家玩这个游戏以来所得的最高分;打印按钮则会打印自己的具体得分情况
主体
首先制作打开程序时出现的”登录”界面,即该程序的mainwindow:
样式:
这里要注意的是,只有当输入完姓名后才能出现下面的提示文字等控件,所以应事先将其属性定为隐藏,点击”commit”按钮后触发事件
private void btm_commit_click(object sender, RoutedEventArgs e) { if (TBox1.Text.Length>0&&TBox1.Text.Length<10)//判断玩家输入的文字长度,更为严谨的做法应该是判断字母+数字的长度,以及玩家输入的字符串不符合时应出现提示信息 { storage.name = TBox1.Text;//定义在storage类中的静态变量,为了存储玩家名称,成绩等信息 TBlock2.Text = "Hi " + storage.name + ". Welcome to the battlefield!Now,lets begin the game!!!Hey,do you want to place a bomb first?";//其实应该直接在前台代码中写好内容,不必在后台再赋值,因多次修改代码所致 TBlock2.Visibility = Visibility.Visible;//显示提示文本块 RB1.Visibility = Visibility.Visible;//显示单选按钮,让用户选择是否先手 RB2.Visibility = Visibility.Visible;//同上 btm_fight.Visibility = Visibility.Visible;//显示进入游戏界面的按钮 btm_commit.IsEnabled = false;//禁止玩家再次点击commit按钮 } }
在玩家确定好是否先手后,就该点击Fight!按钮进入游戏界面了
private void to_main_page_click(object sender, RoutedEventArgs e) { if(RB1.IsChecked==true)//玩家点击"yes"按钮时,设置静态布尔类型变量RButton的值并进入游戏界面"mainpage" { RButton = true; this.Content = new mainpage(); } else if (RB2.IsChecked == true)//玩家点击"no"按钮后,类同yes { RButton = false; this.Content = new mainpage(); } else//玩家没有点击单选按钮的情形,出现提示信息并不触发进入游戏界面的事件,其实想想是否让程序预先设定好"yes"单选按钮就没有这一步了呢? { TBcheck.Visibility = Visibility.Visible; } }
其次,开始制作井字棋程序最复杂的游戏部分,即mainpage
样式:
在拖好控件后,自然要去实现他们的功能.首先是九宫格,我的想法是玩家(假设是玩家先手,并永远下”X”棋)下出第一步棋后,按钮打印出”X”字母,并且在后台的对应于该按钮的值变为1;而电脑(永远下”O”棋)下棋后,按钮打印出”O”字母,并且在后台的对应于该按钮的值变为-1;而没有下任何棋的按钮则不会打印出任何字母,并且在后台的对应于该按钮的值为0.
private void Btm0_Click(object sender, RoutedEventArgs e)//按钮点击触发事件,即玩家点击后的结果.9个按钮均与此类似 { if (btm[btm0]==0)//按钮与后台的值组成键值对的字典,判断当按钮后台的值为0时 { btm0.Content="X";//按钮btm0的内容变为"X",打印出"X"字母 btm[btm0] = 1;//按钮后台的值变为1 computer();//电脑的操作,事实上除了下另一步棋外,还执行了判断是否赢或输或平局的函数,因此没有单独列出 } }
三字连成一线的情况总共有8种,为了更快速的判断是否出现了特殊情况(两子一线,三子一线),可以将这些情况列成一个8行3列的数组以供判断函数或者电脑使用
private void update() { array_for_judge[0] = new int[3] { btm[btm0], btm[btm1], btm[btm2] };//第一行3子 array_for_judge[1] = new int[3] { btm[btm3], btm[btm4], btm[btm5] };//第二行3子 array_for_judge[2] = new int[3] { btm[btm6], btm[btm7], btm[btm8] };//第三行3子 array_for_judge[3] = new int[3] { btm[btm0], btm[btm3], btm[btm6] };//第一列3子 array_for_judge[4] = new int[3] { btm[btm1], btm[btm4], btm[btm7] };//第二列3子 array_for_judge[5] = new int[3] { btm[btm2], btm[btm5], btm[btm8] };//第三列3子 array_for_judge[6] = new int[3] { btm[btm0], btm[btm4], btm[btm8] };//右斜3子 array_for_judge[7] = new int[3] { btm[btm2], btm[btm4], btm[btm6] };//左斜3子 }
每次玩家或者电脑走完一步棋后,都得判断是否出现赢或输或平局的情况,若出现,将刷新棋盘并记录信息
private void judge()//判断函数 { update();//更新信息 foreach (int[] tmp in array_for_judge) { if (Array.TrueForAll(tmp, isone => (isone == 1)) == true)//判断3子全为1,即玩家连成3子的情况 { MessageBox.Show("you win!");//弹出消息框,玩家赢 storage.battle++;//storage类的静态变量,存储对局次数 storage.win++;//同,存储玩家赢的次数 flush();//刷新棋盘,即设置按钮文本全为空,后台值全为0,在此不单独列出该函数 } else if (Array.TrueForAll(tmp, isone => (isone == -1)) == true)//判断3子全为-1,即电脑连成3子的情况 { MessageBox.Show("you lose!"); storage.battle++; storage.lose++; flush(); } } if (btm.ContainsValue(0) == false)//最后判断没有子为0,即棋盘下满仍没有胜负的情况,平局 { MessageBox.Show("draw!"); storage.battle++; storage.tie++; flush(); } }
电脑也需要根据棋盘的形势下棋,在此列出3种情况:
1. 当电脑的棋子已有2子一线,并且该线无第3子时,下第3子取得胜利
2. 当玩家的棋子已有2子一线,并且该线无第3子时,下第3子阻止玩家取得胜利
3. 当无以上情况时,随机选择并落子
private int computer()//返回值是为了跳出该函数用的,并无太大意义 { judge();//首先为玩家判断是否已出现能赢或平局的可能 if (btm.ContainsValue(1) == false&&btm.ContainsValue(-1)==false)//判断按钮的值全为0的情形,即棋盘已被刷新,跳出该函数 { return 0; } for (int i = 0; i < array_for_judge.Length; i++)//进行特殊情况判断 { if (array_for_judge[i].Sum() == -2)//判断2子为-1,另1子为0的情况,即第一种情况 { int j = Array.IndexOf(array_for_judge[i], 0); btm[to_dic_int(i, j)] = -1;//这里我不知道如何从已列出特殊情形的数组中取得原本按钮的信息,只好采取最笨拙的方式--定义函数建立特殊情形数组与按钮的映射,设置按钮的值为-1 to_dic_int(i, j).Content()="O";//设置按钮的内容为"O" judge();//再次进行胜负判断 return 0; } if (array_for_judge[i].Sum() == 2)//阻止玩家获胜的情形 { int j = Array.IndexOf(array_for_judge[i], 0); btm[to_dic_int(i, j)] = -1; to_dic_int(i, j).Background = storage.getImage2(); judge(); return 1; } } Random random = new Random();//随机落子的情形 while (true)无限循环直至随机落子并且该按钮的值为0 { int tmp = random.Next(24); int itmp = tmp % 8; int jtmp = tmp % 3; if (array_for_judge[itmp][jtmp] == 0) { btm[to_dic_int(itmp, jtmp)] = -1; to_dic_int(itmp, jtmp).Background = storage.getImage2(); judge(); return 2; } } }
还要设置电脑先手的情况
if (MainWindow.RButton == false)//在游戏界面初始化时进行判断,当玩家之前选择false单选按钮时让电脑先执行一步 { first_computer();//随机让电脑在九宫格中落子 }
Show Help按钮
private void btm_tips_click(object sender, RoutedEventArgs e) { if (text_tips.Text == "")//事先设置好tips文本块,不过内容为空 { text_tips.Text = "Play The Battle of Waterloo! Start by placing bombs. The enemy will situate a bomb after you.";//显示提示文本 btm_tips.Content = "Hide Help";//更改Show Help按钮的内容 } else//显示文本块内容后,再次点击按钮 { text_tips.Text = ""; btm_tips.Content = "Show Help"; } }
Show Score按钮
private void main_to_score(object sender, RoutedEventArgs e) { score_page score = new score_page();//建立score窗口对象 score.Show();//显示score窗口 }
Exit按钮
private void Exit_click(object sender, RoutedEventArgs e) { Application.Current.Shutdown();//退出程序 }
最后,制作井字棋的得分界面,即score_page
拖几个文本块的事情…值得注意的是,右边的分数需事先读取玩家数据并将其显示出来
Score_player.Text = storage.name;Score_battles.Text = storage.battle.ToString();Score_win.Text = storage.win.ToString();Score_lose.Text = storage.lose.ToString();Score_tie.Text = storage.tie.ToString();
Top Score和Print按钮的功能我还没有实现.Top Score应该是事先读取存储文件中的最高分的数据并用文本块显示出来;而Print则应弹出文件资源管理器让玩家选择保存数据的位置,然后将其保存
总结
这个程序我搞了很长时间才让其具备初始的功能,仍然有许多不完善的地方,比如界面的设计啦,数值的绑定啦等等.不过在这次编写C#程序后可能我的下一次编写就又不知道是什么时候了233,因此我希望在这几天完善完善比较好.
其实老师的要求是埋下地雷而不是井字棋,游戏的名称叫做”滑铁卢战役”,实际上和井字棋一摸一样-.-,附上改”X”“O”为地雷图片的图:
- C#-wpf一个简单的井字棋程序
- 一个简单的C程序
- 一个简单的C程序
- 一个简单的计算器程序(C++)
- 一个简单C程序引发的讨论
- 一个简单的C语言程序
- 一个简单C程序的反编译。
- 一个简单计算器的c程序
- 一个简单C程序的结构
- 一个最简单的Objective C 程序
- 一个简单的C语言小程序
- 一个简单的C/S 架构程序
- 反汇编一个简单的C程序
- 反汇编一个简单的C程序
- 反汇编一个简单的C程序
- 一个简单的C语言加密程序
- 一个简单的c/c++程序
- 反汇编一个简单的C程序
- Connection refused by [127.0.0.1]
- 关于Idea热部署,修改代码不需要重启tomcat
- 用python学概率与统计(第二章)描述性统计:表格法,图形法
- Design a HashMap class in C++. Implement put, get methods.
- PE格式解析-区段表及导入表结构详解
- C#-wpf一个简单的井字棋程序
- Laravel 5.5 .No application encryption key has been specified
- [Search Engines笔记]17: Authority metrics
- java web学习路线
- web缓冲机制
- web负载均衡
- 解决多线程并发问题
- JAVA中重写equals()方法的同时要重写hashcode()方法
- jdk 1.5 1.6 1.7 加入新特性