用面向对象写猜拳游戏
今天打算写一个猜拳游戏,也就是我们小时候玩的石头剪刀布.我写的一个小程序的样子如下:
也是很简单的,有三个button是供玩家选择的,当玩家选择某一个button时,玩家后面的label就显示玩家选择的内容,比如如果玩家选择出石头,则玩家后面的那个label则显示石头,以此类推.电脑则是随机选择出石头或者剪刀或者布.当然出完后将结果显示出来,也就是在正中间的那个label上显示出比赛结果来(当然实际的时候尽量是将此要显示的三个label设置为空格,体验略好一点,不过放说回来,小程序体验貌似就这样子).就是这样的一个小程序.
那么在这个小程序里,简单的说就是要将三个label显示出内容来,我们就当是这个程序是写一个填空题,正确的完成三个空格也就可以了.只是其需要满足于玩家的label的满足于玩家点什么显示什么.电脑的label是随机显示三个中其的一个.然后比较结果的label就根据其两者出拳的内容将比较的输赢显示出来也就好了.那么,我们就可以建三个类,第一个类是玩家类,用于显示玩家出拳的结果,完成第一个空格也就是用于.第二个类是电脑类,用于显示电脑的出拳结果,此用于完成第二个空格.最后一个类是裁判类,用于根据玩家和电脑的出拳结果,显示出成绩的结果,此类用于完成第三个空格.
关于裁判类的话我们发现比较的话最好是用数字比较好一点.那么我们这里可以用1表示石头,2表示剪刀,3表示布,裁判类这块的放就可以用玩家所表示的数字减去电脑出拳内容表示的数字来判断,当玩家和电脑出拳的内容为零时,则说明他们是出的一样的,则表示平手,如果是结果等于-1(当石头对剪刀,剪刀对布)或者2(布和石头)时,则说明用户赢了,其他情况则表示电脑赢了.
玩家类里有一个存储出拳内容的一个属性,和一个将根据出拳内容将其结果转换成数字用于比较一个方法,其代码如下:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace _2014022203Sat猜拳游戏 8 { 9 class Player 10 { 11 //此属性用于存储出拳的内容. 12 public string FistName { get; set; } 13 /// <summary> 14 /// 此方法将出拳之结果成数字,以便比较 15 /// </summary> 16 /// <param name="fist">将出拳的内容当参数传递</param> 17 /// <returns>将数字返回</returns> 18 public int ShowFist(string fist) 19 { 20 //将传进来的参数给存储出拳内容的属性. 21 this.FistName = fist; 22 int result = -1; 23 switch (fist) 24 { 25 case "石头": 26 result = 1; 27 break; 28 case "剪刀": 29 result = 2; 30 break; 31 case "布": 32 result = 3; 33 break; 34 } 35 return result; 36 } 37 } 38 }
电脑类里也有一个存储出拳内容的一个属性和一个随机产生出拳内容的方法.此处用数字随机.便于比较.其代码如下:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace _2014022203Sat猜拳游戏 8 { 9 class Computer 10 { 11 //此属性用于存储出拳(udr)的内容. 12 public string FistName { get; set; } 13 /// <summary> 14 /// 此方法用于得到得到出拳的内容 15 /// </summary> 16 /// <returns>将得到的内容返回</returns> 17 public int ShowFist() 18 { 19 Random random = new Random(); 20 int r = random.Next(1, 4); 21 switch (r) 22 { 23 case 1: 24 this.FistName = "石头"; 25 break; 26 case 2: 27 this.FistName = "剪刀"; 28 break; 29 case 3: 30 this.FistName = "布"; 31 break; 32 } 33 return r; 34 } 35 } 36 }
裁判类里就一个方法,根据玩家出拳内容代表的数字和电脑出拳内容代表的数字得到比较结果.其代码如下:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace _2014022203Sat猜拳游戏 8 { 9 class Referee 10 { 11 public string Result(int player, int computer) 12 { 13 if (player-computer==-1||player-computer==2) 14 { 15 return "亡口月贝凡"; 16 } 17 else if (player-computer==0) 18 { 19 return "平手"; 20 } 21 else 22 { 23 return "LOSE"; 24 } 25 } 26 } 27 }
当点击三个按钮时的代码则是根据三个类将这个填空题正确的完成,其代码如下:
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 using System.Windows.Forms; 10 11 namespace _2014022203Sat猜拳游戏 12 { 13 public partial class Form1 : Form 14 { 15 public Form1() 16 { 17 InitializeComponent(); 18 } 19 20 private void stone_button_Click(object sender, EventArgs e) 21 { 22 //Button btn = (Button) sender; 23 //if (btn!=null) 24 //{ 25 Player player = new Player(); 26 //下面这行代码为用玩家类的方法,将玩家选的内容传入,返回一个数字. 27 int playerFist = player.ShowFist(stone_button.Text); 28 //将存储的内容显示到玩家后面的那个label上.完成填空题的第一个空格. 29 lblPalyer.Text = player.FistName; 30 31 Computer computer = new Computer(); 32 //下行这行代码为用电脑类的方法,将为电脑随机产生一个数字,返回一个数字,代表其出拳内容. 33 int computerFist = computer.ShowFist(); 34 //将电脑的出拳内容显示到对应的位置.完成填空题的第二个空格. 35 lblComputer.Text = computer.FistName; 36 37 Referee referee = new Referee(); 38 //此为调用裁判类的方法,将玩家出拳内容所代码的数字和电脑出拳内容所代表的数字传入给出比赛的结果显示到显示比赛结果的那个LABEL上.完成填空题的第三个空格. 39 lblResult.Text = referee.Result(playerFist, computerFist); 40 //} 41 } 42 43 private void scissor_button_Click(object sender, EventArgs e) 44 { 45 Player player = new Player(); 46 int playerFist = player.ShowFist(scissor_button.Text); 47 lblPalyer.Text = player.FistName; 48 49 Computer computer = new Computer(); 50 int computerFist = computer.ShowFist(); 51 lblComputer.Text = computer.FistName; 52 53 Referee referee = new Referee(); 54 lblResult.Text = referee.Result(playerFist, computerFist); 55 } 56 57 private void burlap_button_Click(object sender, EventArgs e) 58 { 59 Player player = new Player(); 60 int playerFist = player.ShowFist(burlap_button.Text); 61 lblPalyer.Text = player.FistName; 62 63 Computer computer = new Computer(); 64 int computerFist = computer.ShowFist(); 65 lblComputer.Text = computer.FistName; 66 67 Referee referee = new Referee(); 68 lblResult.Text = referee.Result(playerFist, computerFist); 69 } 70 } 71 }
那么这样也就完成了这个小程序了.不过写代码的时候我们讲究的是DRP(Do'not Repeter Yourself),那我们发现了点击三个按钮时的代码几乎一样,应该尽量避免这样的代码.那么我们就要了解这个点击事件后面的两个参数的意思了.后面是有两个参数的第一个是sender这个参数,第二个是e这个参数,sender表示的是此事件是谁的事件,e表示的是和事件相关联的一些信息.就比如现在小杜现在踹了小小杜一脚,那么在这个里面sender就表示的是踹的是小小杜这个人,而e这个参数里就是踹的是他的腿还是臀部还是什么其他的地方.sener此参数就表示是谁的事件.那么根据里氏转换原则我们则可以将sender这个对象转换成Button类型的一个对象,然后后面用此对象点出名字也就可以了.后面就不用一个一个的改控件的那个名字了.那么优化后的代码如下:
1 private void scissor_button_Click(object sender, EventArgs e) 2 { 3 //里氏转换 4 Button btn = (Button) sender; 5 if (btn!=null) 6 { 7 Player player = new Player(); 8 int playerFist = player.ShowFist(btn.Text);//此处的不同。 9 lblPalyer.Text = player.FistName; 10 11 Computer computer = new Computer(); 12 int computerFist = computer.ShowFist(); 13 lblComputer.Text = computer.FistName; 14 15 Referee referee = new Referee(); 16 lblResult.Text = referee.Result(playerFist, computerFist); 17 } 18 }
这样的话代码量也就少很多了,就相对来说算是完美一步了.依旧可以做到当选择其他的按钮时此程序依旧可以正常的运行.附图一张: