<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # IronPython Mono Winforms 中的俄羅斯方塊游戲 > [http://zetcode.com/tutorials/ironpythontutorial/tetris/](http://zetcode.com/tutorials/ironpythontutorial/tetris/) 俄羅斯方塊游戲是有史以來最受歡迎的計算機游戲之一。 原始游戲是由俄羅斯程序員 Alexey Pajitnov 于 1985 年設計和編程的。此后,幾乎所有版本的幾乎所有計算機平臺上都可以使用俄羅斯方塊。 甚至我的手機都有俄羅斯方塊游戲的修改版。 俄羅斯方塊被稱為下降塊益智游戲。 在這個游戲中,我們有七個不同的形狀,稱為 tetrominoes 。 S 形,Z 形,T 形,L 形,線形,鏡像 L 形和正方形。 這些形狀中的每一個都形成有四個正方形。 形狀從板上掉下來。 俄羅斯方塊游戲的目的是移動和旋轉形狀,以便它們盡可能地適合。 如果我們設法形成一行,則該行將被破壞并得分。 我們玩俄羅斯方塊游戲,直到達到頂峰。 ![Tetrominoes](https://img.kancloud.cn/2b/7a/2b7a874cd2ec9a34c259d3dd686809e9_328x132.jpg) 圖:Tetrominoes ## 開發 我們的俄羅斯方塊游戲沒有圖像,我們使用 Winforms 庫中可用的繪圖 API 繪制四方塊。 每個計算機游戲的背后都有一個數學模型。 在俄羅斯方塊中也是如此。 游戲背后的一些想法。 * 我們使用`Timer`創建游戲周期 * 繪制四方塊 * 形狀以正方形為單位移動(不是逐個像素移動) * 從數學上講,棋盤是簡單的數字列表 以下示例是俄羅斯方塊游戲的修改版,可用于 PyQt4 安裝文件。 `tetris.py` ```py #!/usr/bin/ipy import clr clr.AddReference("System.Windows.Forms") clr.AddReference("System.Drawing") clr.AddReference("System") from System.Windows.Forms import Application, Form, FormBorderStyle from System.Windows.Forms import UserControl, Keys, Timer, StatusBar from System.Drawing import Size, Color, SolidBrush, Pen from System.Drawing.Drawing2D import LineCap from System.ComponentModel import Container from System import Random class Tetrominoes(object): NoShape = 0 ZShape = 1 SShape = 2 LineShape = 3 TShape = 4 SquareShape = 5 LShape = 6 MirroredLShape = 7 class Board(UserControl): BoardWidth = 10 BoardHeight = 22 Speed = 200 ID_TIMER = 1 def __init__(self): self.Text = 'Snake' self.components = Container() self.isWaitingAfterLine = False self.curPiece = Shape() self.nextPiece = Shape() self.curX = 0 self.curY = 0 self.numLinesRemoved = 0 self.board = [] self.DoubleBuffered = True self.isStarted = False self.isPaused = False self.timer = Timer(self.components) self.timer.Enabled = True self.timer.Interval = Board.Speed self.timer.Tick += self.OnTick self.Paint += self.OnPaint self.KeyUp += self.OnKeyUp self.ClearBoard() def ShapeAt(self, x, y): return self.board[(y * Board.BoardWidth) + x] def SetShapeAt(self, x, y, shape): self.board[(y * Board.BoardWidth) + x] = shape def SquareWidth(self): return self.ClientSize.Width / Board.BoardWidth def SquareHeight(self): return self.ClientSize.Height / Board.BoardHeight def Start(self): if self.isPaused: return self.isStarted = True self.isWaitingAfterLine = False self.numLinesRemoved = 0 self.ClearBoard() self.NewPiece() def Pause(self): if not self.isStarted: return self.isPaused = not self.isPaused statusbar = self.Parent.statusbar if self.isPaused: self.timer.Stop() statusbar.Text = 'paused' else: self.timer.Start() statusbar.Text = str(self.numLinesRemoved) self.Refresh() def ClearBoard(self): for i in range(Board.BoardHeight * Board.BoardWidth): self.board.append(Tetrominoes.NoShape) def OnPaint(self, event): g = event.Graphics size = self.ClientSize boardTop = size.Height - Board.BoardHeight * self.SquareHeight() for i in range(Board.BoardHeight): for j in range(Board.BoardWidth): shape = self.ShapeAt(j, Board.BoardHeight - i - 1) if shape != Tetrominoes.NoShape: self.DrawSquare(g, 0 + j * self.SquareWidth(), boardTop + i * self.SquareHeight(), shape) if self.curPiece.GetShape() != Tetrominoes.NoShape: for i in range(4): x = self.curX + self.curPiece.x(i) y = self.curY - self.curPiece.y(i) self.DrawSquare(g, 0 + x * self.SquareWidth(), boardTop + (Board.BoardHeight - y - 1) * self.SquareHeight(), self.curPiece.GetShape()) g.Dispose() def OnKeyUp(self, event): if not self.isStarted or self.curPiece.GetShape() == Tetrominoes.NoShape: return key = event.KeyCode if key == Keys.P: self.Pause() return if self.isPaused: return elif key == Keys.Left: self.TryMove(self.curPiece, self.curX - 1, self.curY) elif key == Keys.Right: self.TryMove(self.curPiece, self.curX + 1, self.curY) elif key == Keys.Down: self.TryMove(self.curPiece.RotatedRight(), self.curX, self.curY) elif key == Keys.Up: self.TryMove(self.curPiece.RotatedLeft(), self.curX, self.curY) elif key == Keys.Space: self.DropDown() elif key == Keys.D: self.OneLineDown() def OnTick(self, sender, event): if self.isWaitingAfterLine: self.isWaitingAfterLine = False self.NewPiece() else: self.OneLineDown() def DropDown(self): newY = self.curY while newY > 0: if not self.TryMove(self.curPiece, self.curX, newY - 1): break newY -= 1 self.PieceDropped() def OneLineDown(self): if not self.TryMove(self.curPiece, self.curX, self.curY - 1): self.PieceDropped() def PieceDropped(self): for i in range(4): x = self.curX + self.curPiece.x(i) y = self.curY - self.curPiece.y(i) self.SetShapeAt(x, y, self.curPiece.GetShape()) self.RemoveFullLines() if not self.isWaitingAfterLine: self.NewPiece() def RemoveFullLines(self): numFullLines = 0 statusbar = self.Parent.statusbar rowsToRemove = [] for i in range(Board.BoardHeight): n = 0 for j in range(Board.BoardWidth): if not self.ShapeAt(j, i) == Tetrominoes.NoShape: n = n + 1 if n == 10: rowsToRemove.append(i) rowsToRemove.reverse() for m in rowsToRemove: for k in range(m, Board.BoardHeight): for l in range(Board.BoardWidth): self.SetShapeAt(l, k, self.ShapeAt(l, k + 1)) numFullLines = numFullLines + len(rowsToRemove) if numFullLines > 0: self.numLinesRemoved = self.numLinesRemoved + numFullLines statusbar.Text = str(self.numLinesRemoved) self.isWaitingAfterLine = True self.curPiece.SetShape(Tetrominoes.NoShape) self.Refresh() def NewPiece(self): self.curPiece = self.nextPiece statusbar = self.Parent.statusbar self.nextPiece.SetRandomShape() self.curX = Board.BoardWidth / 2 + 1 self.curY = Board.BoardHeight - 1 + self.curPiece.MinY() if not self.TryMove(self.curPiece, self.curX, self.curY): self.curPiece.SetShape(Tetrominoes.NoShape) self.timer.Stop() self.isStarted = False statusbar.Text = 'Game over' def TryMove(self, newPiece, newX, newY): for i in range(4): x = newX + newPiece.x(i) y = newY - newPiece.y(i) if x < 0 or x >= Board.BoardWidth or y < 0 or y >= Board.BoardHeight: return False if self.ShapeAt(x, y) != Tetrominoes.NoShape: return False self.curPiece = newPiece self.curX = newX self.curY = newY self.Refresh() return True def DrawSquare(self, g, x, y, shape): colors = [ (0, 0, 0), (204, 102, 102), (102, 204, 102), (102, 102, 204), (204, 204, 102), (204, 102, 204), (102, 204, 204), (218, 170, 0) ] light = [ (0, 0, 0), (248, 159, 171), (121, 252, 121), (121, 121, 252), (252, 252, 121), (252, 121, 252), (121, 252, 252), (252, 198, 0) ] dark = [ (0, 0, 0), (128, 59, 59), (59, 128, 59), (59, 59, 128), (128, 128, 59), (128, 59, 128), (59, 128, 128), (128, 98, 0) ] pen = Pen(Color.FromArgb(light[shape][0], light[shape][1], light[shape][2]), 1) pen.StartCap = LineCap.Flat pen.EndCap = LineCap.Flat g.DrawLine(pen, x, y + self.SquareHeight() - 1, x, y) g.DrawLine(pen, x, y, x + self.SquareWidth() - 1, y) darkpen = Pen(Color.FromArgb(dark[shape][0], dark[shape][1], dark[shape][2]), 1) darkpen.StartCap = LineCap.Flat darkpen.EndCap = LineCap.Flat g.DrawLine(darkpen, x + 1, y + self.SquareHeight() - 1, x + self.SquareWidth() - 1, y + self.SquareHeight() - 1) g.DrawLine(darkpen, x + self.SquareWidth() - 1, y + self.SquareHeight() - 1, x + self.SquareWidth() - 1, y + 1) g.FillRectangle(SolidBrush(Color.FromArgb(colors[shape][0], colors[shape][1], colors[shape][2])), x + 1, y + 1, self.SquareWidth() - 1, self.SquareHeight() - 2) pen.Dispose() darkpen.Dispose() class Shape(object): coordsTable = ( ((0, 0), (0, 0), (0, 0), (0, 0)), ((0, -1), (0, 0), (-1, 0), (-1, 1)), ((0, -1), (0, 0), (1, 0), (1, 1)), ((0, -1), (0, 0), (0, 1), (0, 2)), ((-1, 0), (0, 0), (1, 0), (0, 1)), ((0, 0), (1, 0), (0, 1), (1, 1)), ((-1, -1), (0, -1), (0, 0), (0, 1)), ((1, -1), (0, -1), (0, 0), (0, 1)) ) def __init__(self): self.coords = [[0,0] for i in range(4)] self.pieceShape = Tetrominoes.NoShape self.SetShape(Tetrominoes.NoShape) def GetShape(self): return self.pieceShape def SetShape(self, shape): table = Shape.coordsTable[shape] for i in range(4): for j in range(2): self.coords[i][j] = table[i][j] self.pieceShape = shape def SetRandomShape(self): rand = Random() self.SetShape(rand.Next(1, 7)) def x(self, index): return self.coords[index][0] def y(self, index): return self.coords[index][1] def SetX(self, index, x): self.coords[index][0] = x def SetY(self, index, y): self.coords[index][1] = y def MaxX(self): m = self.coords[0][0] for i in range(4): m = max(m, self.coords[i][0]) return m def MinY(self): m = self.coords[0][1] for i in range(4): m = min(m, self.coords[i][1]) return m def RotatedLeft(self): if self.pieceShape == Tetrominoes.SquareShape: return self result = Shape() result.pieceShape = self.pieceShape for i in range(4): result.SetX(i, self.y(i)) result.SetY(i, -self.x(i)) return result def RotatedRight(self): if self.pieceShape == Tetrominoes.SquareShape: return self result = Shape() result.pieceShape = self.pieceShape for i in range(4): result.SetX(i, -self.y(i)) result.SetY(i, self.x(i)) return result class IForm(Form): def __init__(self): self.Text = 'Tetris' self.Width = 200 self.Height = 430 self.FormBorderStyle = FormBorderStyle.FixedSingle board = Board() board.Width = 195 board.Height = 380 self.Controls.Add(board) self.statusbar = StatusBar() self.statusbar.Parent = self self.statusbar.Text = 'Ready' board.Start() self.CenterToScreen() Application.Run(IForm()) ``` 我對游戲做了一些簡化,以便于理解。 游戲啟動后立即開始。 我們可以通過按`p`鍵暫停游戲。 空格鍵將把俄羅斯方塊放在底部。 `d` 鍵會將棋子下降一行。 (它可以用來加快下降速度。)游戲以恒定速度運行,沒有實現加速。 分數是我們已刪除的行數。 ```py class Tetrominoes(object): NoShape = 0 ZShape = 1 SShape = 2 LineShape = 3 TShape = 4 SquareShape = 5 LShape = 6 MirroredLShape = 7 ``` tetrominoes 有七種不同類型。 ```py ... self.curX = 0 self.curY = 0 self.numLinesRemoved = 0 self.board = [] ... ``` 在開始游戲周期之前,我們先初始化一些重要的變量。 `self.board`變量是`Tetrominoes`的列表。 它表示各種形狀的位置以及板上形狀的其余部分。 ```py def ClearBoard(self): for i in range(Board.BoardHeight * Board.BoardWidth): self.board.append(Tetrominoes.NoShape) ``` `ClearBoard()`方法清除電路板。 它用`Tetrominoes.NoShape`值填充`self.board`變量。 俄羅斯方塊游戲中的繪圖是通過`OnPaint()`方法完成的。 ```py for i in range(Board.BoardHeight): for j in range(Board.BoardWidth): shape = self.shapeAt(j, Board.BoardHeight - i - 1) if shape != Tetrominoes.NoShape: self.drawSquare(g, 0 + j * self.squareWidth(), boardTop + i * self.squareHeight(), shape) ``` 游戲的繪圖分為兩個步驟。 在第一步中,我們繪制所有形狀或已放置到板底部的形狀的其余部分。 所有正方形都將記住在`self.board`列表中。 我們使用`ShapeAt()`方法訪問它。 ```py if self.curPiece.shape() != Tetrominoes.NoShape: for i in range(4): x = self.curX + self.curPiece.x(i) y = self.curY - self.curPiece.y(i) self.drawSquare(g, 0 + x * self.squareWidth(), boardTop + (Board.BoardHeight - y - 1) * self.squareHeight(), self.curPiece.shape()) ``` 下一步是繪制掉落的實際零件。 在`OnKeyUp()`方法中,我們檢查按鍵是否按下。 ```py elif key == Keys.Left: self.tryMove(self.curPiece, self.curX - 1, self.curY) ``` 如果按向左箭頭鍵,我們將嘗試將棋子向左移動。 我們說嘗試,因為這片可能無法移動。 在`TryMove()`方法中,我們嘗試移動形狀。 如果無法移動該片段,則返回`False`。 ```py for i in range(4): x = newX + newPiece.x(i) y = newY - newPiece.y(i) if x < 0 or x >= Board.BoardWidth or y < 0 or y >= Board.BoardHeight: return False if self.ShapeAt(x, y) != Tetrominoes.NoShape: return False ``` 如果形狀在板的邊緣或與其他零件相鄰,則返回`False`。 ```py self.curPiece = newPiece self.curX = newX self.curY = newY self.Refresh() return True ``` 否則,我們將當前的下降片放到新位置并返回`True`。 ```py def OnTick(self, sender, event): if self.isWaitingAfterLine: self.isWaitingAfterLine = False self.NewPiece() else: self.OneLineDown() ``` 在`OnTick()`方法中,我們要么在前一個擊中底部之后創建一個新片段,要么將下降的片段向下移動一行。 如果片段觸底,我們將調用`RemoveFullLines()`方法。 首先,我們找出所有實線。 ```py rowsToRemove = [] for i in range(Board.BoardHeight): n = 0 for j in range(Board.BoardWidth): if not self.ShapeAt(j, i) == Tetrominoes.NoShape: n = n + 1 if n == 10: rowsToRemove.append(i) ``` 我們在董事會中循環。 一排可以有十個形狀。 如果該行已滿,例如 n 等于 10,我們存儲行號以供以后刪除。 ```py rowsToRemove.reverse() for m in rowsToRemove: for k in range(m, Board.BoardHeight): for l in range(Board.BoardWidth): self.SetShapeAt(l, k, self.ShapeAt(l, k + 1)) ``` 這些代碼行將刪除所有行。 我們顛倒了`rowsToRemove`列表的順序,因此我們從最底部的全行開始。 我們要做的是通過將一行中的所有行向下放置一行來刪除整行。 對于所有實線都會發生這種情況。在我們的情況下,我們使用天真重力。 這意味著碎片可能漂浮在空的間隙上方。 ```py def NewPiece(self): self.curPiece = self.nextPiece statusbar = self.Parent.statusbar self.nextPiece.SetRandomShape() self.curX = Board.BoardWidth / 2 + 1 self.curY = Board.BoardHeight - 1 + self.curPiece.MinY() if not self.TryMove(self.curPiece, self.curX, self.curY): self.curPiece.SetShape(Tetrominoes.NoShape) self.timer.Stop() self.isStarted = False statusbar.Text = 'Game over' ``` `NewPiece()`方法隨機創建一個新的俄羅斯方塊。 如果棋子無法進入其初始位置,例如 `TryMove()`方法返回`False`,游戲結束。 ```py colors = [ (0, 0, 0), (204, 102, 102), ... ] light = [ (0, 0, 0), (248, 159, 171), ... ] dark = [ (0, 0, 0), (128, 59, 59), ... ] ``` 一共有三種顏色。 `colours`列表存儲正方形填充的顏色值。 七塊每個都有其自己的顏色。 `light`和`dark`存儲線條的顏色,使正方形看起來像 3D。 這些顏色是相同的,只是越來越淺。 我們將在正方形的頂部和左側繪制兩條淺色的線條,并在右側和底部繪制兩條深色的線條。 ```py g.DrawLine(pen, x, y + self.SquareHeight() - 1, x, y) g.DrawLine(pen, x, y, x + self.SquareWidth() - 1, y) ``` 這兩條線繪制一個正方形的亮線。 `Shape`類保存有關俄羅斯方塊的信息。 ```py self.coords = [[0,0] for i in range(4)] ``` 創建后,我們將創建一個空坐標列表。 該列表將保存俄羅斯方塊的坐標。 例如,這些元組(0,-1),(0,0),(1,0),(1,1)表示旋轉的 S 形。 下圖說明了形狀。 ![Coordinates](https://img.kancloud.cn/5c/0b/5c0bbb2ed04c22b46915ea1ef803ce4d_272x230.jpg) 圖:坐標 當繪制當前下降片時,將其繪制在`self.curX`和`self.curY`位置。 然后,我們查看坐標表并繪制所有四個正方形。 `RotateLeft()`方法將一塊向左旋轉。 ```py if self.pieceShape == Tetrominoes.SquareShape: return self ``` 如果我們有`Tetrominoes.SquareShape`個,我們什么也不做。 此形狀始終相同。 ```py result = Shape() result.pieceShape = self.pieceShape for i in range(4): result.SetX(i, self.y(i)) result.SetY(i, -self.x(i)) return result ``` 在其他情況下,我們更改作品的坐標。 要了解此代碼,請查看上圖。 ![Tetris](https://img.kancloud.cn/3a/52/3a52f5a884e19840d9c1d591c04d9daf_202x433.jpg) 圖:俄羅斯方塊 這是 IronPython Winforms 中的俄羅斯方塊游戲。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看