#include <LiquidCrystal.h>
#include <SPI.h>
#include "Tetris.h"
#define SS_PIN 10
void setup() {
  // put your setup code here, to run once:
  lcd.begin(16, 2);
  lcd.print("   Score: 0");
  Serial.begin(9600);
  randomSeed(analogRead(0));
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  Serial.println("Loading ...");
  Dp_Init();
  Te_Init();
  Serial.println(random(9, 15) * (10 + pow(3,1) * 10));
  Serial.println(random(9, 15) * (10 + pow(3,2) * 10));
  Serial.println(random(9, 15) * (10 + pow(3,3) * 10));
  Serial.println(random(9, 15) * (10 + pow(3,4) * 10));
}
byte xC = 0;
byte yC = 0;
long frameCount = 0;
void loop() {
  // put your main code here, to run repeatedly:
  frameCount++;
  Te_Draw();
  Te_Update(frameCount);
  delay(1);
}
#include <LiquidCrystal.h>
#include <SPI.h>
#define SS_PIN 10
#define DP_HEIGHT 16
#define DP_WIDTH 10
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
void Dp_DrawLine(int x, int y, int length, bool hori, bool isSet);
struct ZeichenFlaeche {
  byte grid[8] = {
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000
};
};
ZeichenFlaeche zeichen[2][2]; 
void Dp_Init()
{
  lcd.createChar(0, zeichen[0][0].grid);
  lcd.createChar(1, zeichen[0][1].grid);
  lcd.createChar(2, zeichen[1][0].grid);
  lcd.createChar(3, zeichen[1][1].grid);
  Dp_DrawLine(0,0,10,true,true); // Linie Oben H
  Dp_DrawLine(0,15,10,true,true); // Linie Unten H
  Dp_DrawLine(0,0,16,false,true); // Linie Links V
  Dp_DrawLine(9,0,16,false,true); // Linie Rechts V
}
void Dp_Draw()
{
  lcd.createChar(0, zeichen[0][0].grid);
  lcd.createChar(1, zeichen[0][1].grid);
  lcd.createChar(2, zeichen[1][0].grid);
  lcd.createChar(3, zeichen[1][1].grid);
  lcd.setCursor(0, 0);
  lcd.write(byte(0));
  
  lcd.setCursor(0, 1);
  lcd.write(byte(1));
  
  lcd.setCursor(1, 0);
  lcd.write(byte(2));
  
  lcd.setCursor(1, 1);
  lcd.write(byte(3));
}
void Dp_SetPixel(int x, int y, bool isOn)
{
  if(isOn)
    bitSet  (zeichen[x/5][y/8].grid[y%8],4-x%5);
  else 
    bitClear(zeichen[x/5][y/8].grid[y%8],4-x%5);
}
bool Dp_GetPixel(int x, int y)
{
  return bitRead(zeichen[x/5][y/8].grid[y%8],4-x%5)==1?true:false;
}
void Dp_DrawLine(int x, int y, int length, bool hori, bool isSet)
{
  for(int offset = 0; offset < length; offset++)
  {
    if(hori)
      Dp_SetPixel(x + offset, y, isSet);
    else
      Dp_SetPixel(x, y + offset, isSet);
  }
}
#include "Display.h"
#define TE_WIDTH (DP_WIDTH - 2)
#define TE_HEIGHT (DP_HEIGHT - 2)
enum Stone_Type {
  TStone = 0,
  LStone = 1,
  IStone = 2,
  SStone = 3,
  ZStone = 5,
  OStone = 4,
};
struct Stone {
  byte field[4];
  char x = TE_WIDTH / 2 - 1;
  char y = 1;
  char rot = 0;
  Stone_Type type;
};
Stone St_InitStone();
bool St_HitTest(Stone st)
{
  for(char x = 0; x < 5; x++) // Zeilen eines Steins
  {
    for(char y = 0; y < 4; y++) // Spalten eines Steins
    {
      if(bitRead(st.field[y],x) == 1) // Ist der aktuelle Stein Pixel gesetzt?
      {
        char xT = st.x  + x; // Absolute x Position
        char yT = st.y + y;  // Absolute y Position
        if(xT < 1 || xT > TE_WIDTH || yT < 1 || yT > TE_HEIGHT) // Aktueller Stein Pixel aus dem Fenster.
        {
          Serial.print("HIT OUTWINDOW xT=");
          Serial.print(xT, DEC);
          Serial.print(" yT=");
          Serial.println(yT, DEC);
          return true;
        }
        if(Dp_GetPixel(xT,yT)) // Aktueller Stein Pixel auf dem Display ist belegt.
        {
          Serial.print("HIT Pixel xT=");
          Serial.print(xT, DEC);
          Serial.print(" yT=");
          Serial.println(yT, DEC);
          return true;
        }
      }
    }
  }
  return false;
}
void St_Print(Stone st, bool printIt)
{
  for(char x = 0; x < 5; x++)
  {
    for(char y = 0; y < 4; y++)
    {
      if(bitRead(st.field[y],x) == 1)
      {
        char xT = st.x  + x;
        char yT = st.y + y;
        if(xT < 1 || xT > TE_WIDTH || yT < 1 || yT > TE_HEIGHT) // Aktueller Stein Pixel aus dem Fenster.
          continue;
        Dp_SetPixel(xT, yT, printIt);
      }
    }
  }
}
void St_SetRot(Stone *st, char rot)
{
  (*st).rot = rot;
  switch((*st).type)
  {
    case TStone: 
    {
      switch(rot)
      {
        case 0: 
        {
          (*st).field[0] = B00000;
          (*st).field[1] = B00100;
          (*st).field[2] = B01110;
          (*st).field[3] = B00000;
        } break;
        case 1: 
        {
          (*st).field[0] = B00000;
          (*st).field[1] = B00100;
          (*st).field[2] = B00110;
          (*st).field[3] = B00100;
        } break;
        case 2: 
        {
          (*st).field[0] = B00000;
          (*st).field[1] = B00000;
          (*st).field[2] = B01110;
          (*st).field[3] = B00100;
        } break;
        case 3: 
        {
          (*st).field[0] = B00000;
          (*st).field[1] = B00100;
          (*st).field[2] = B01100;
          (*st).field[3] = B00100;
        } break;
      }
    } break;
    
    case LStone: 
    {
      switch(rot)
      {
        case 0: 
        {
          (*st).field[0] = B00000;
          (*st).field[1] = B00010;
          (*st).field[2] = B01110;
          (*st).field[3] = B00000;
        } break;
        case 1: 
        {
          (*st).field[0] = B00000;
          (*st).field[1] = B00100;
          (*st).field[2] = B00100;
          (*st).field[3] = B00110;
        } break;
        case 2: 
        {
          (*st).field[0] = B00000;
          (*st).field[1] = B00000;
          (*st).field[2] = B01110;
          (*st).field[3] = B01000;
        } break;
        case 3: 
        {
          (*st).field[0] = B00000;
          (*st).field[1] = B01100;
          (*st).field[2] = B00100;
          (*st).field[3] = B00100;
        } break;
      }
    } break;
    
    case IStone: 
    {
      switch(rot)
      {
        case 0: 
        case 2: 
        {
          (*st).field[0] = B00100;
          (*st).field[1] = B00100;
          (*st).field[2] = B00100;
          (*st).field[3] = B00100;
        } break;
        
        case 1:
        case 3: 
        {
          (*st).field[0] = B00000;
          (*st).field[1] = B00000;
          (*st).field[2] = B01111;
          (*st).field[3] = B00000;
        } break;
      }
    } break;
    
    case SStone: 
    {
      switch(rot)
      {
        case 0: 
        {
          (*st).field[0] = B00000;
          (*st).field[1] = B01100;
          (*st).field[2] = B00110;
          (*st).field[3] = B00000;
        } break;
        case 1: 
        {
          (*st).field[0] = B00000;
          (*st).field[1] = B00100;
          (*st).field[2] = B01100;
          (*st).field[3] = B01000;
        } break;
        case 2: 
        {
          (*st).field[0] = B00000;
          (*st).field[1] = B01100;
          (*st).field[2] = B00110;
          (*st).field[3] = B00000;
        } break;
        case 3: 
        {
          (*st).field[0] = B00000;
          (*st).field[1] = B00010;
          (*st).field[2] = B00110;
          (*st).field[3] = B00100;
        } break;
      }
    } break;
    case OStone: 
    {
      switch(rot)
      {
        case 0: 
        case 1: 
        case 2: 
        case 3: 
        {
          (*st).field[0] = B00000;
          (*st).field[1] = B01100;
          (*st).field[2] = B01100;
          (*st).field[3] = B00000;
        } break;
      }
    } break;
    
    default: break;
  }
}
void St_Rotate(Stone *st)
{
  St_SetRot(st, ((*st).rot+1)%4);
}
void St_BackRotate(Stone *st)
{
  char rot = (*st).rot - 1;
  if(rot == -1)
  rot = 3;
  St_SetRot(st, rot);
}
Stone St_InitStone()
{
  Stone st;
  st.type = (Stone_Type)random(0,5);
  St_SetRot(&st, 0);
  return st;
}
#include "Stone.h"
#define BUTTON_LEFT 13
#define BUTTON_RIGHT 12
#define BUTTON_ROT 11
#define BUTTON_DOWN 10
bool BUTTON_LEFT_LAST = false;
bool BUTTON_RIGHT_LAST = false;
bool BUTTON_ROT_LAST = false;
bool BUTTON_DOWN_LAST = false;
long points = 0;
Stone currentStone;
void Te_Init()
{
  currentStone = St_InitStone();
  pinMode(BUTTON_LEFT, INPUT_PULLUP);
  pinMode(BUTTON_RIGHT, INPUT_PULLUP);
  pinMode(BUTTON_DOWN, INPUT_PULLUP);  
}
void Te_Draw()
{
  St_Print(currentStone, true);
  Dp_Draw();
  St_Print(currentStone, false);
}
void Te_AddPoints(long p)
{
  points += p;
  lcd.setCursor(10, 0);
  lcd.print(points);
}
void Te_DeleteRow(int row)
{
  bool sw = true;
  for (int i = 0; i < 15; i++)
  {
    Dp_DrawLine(1, row, 8, true, sw);
    Dp_DrawLine(0,0,10,true,!sw); // Linie Oben H
    Dp_DrawLine(0,15,10,true,!sw); // Linie Unten H
    Dp_DrawLine(0,0,16,false,!sw); // Linie Links V
    Dp_DrawLine(9,0,16,false,!sw); // Linie Rechts V
    Dp_Draw();
    delay(90);
    sw = sw ? false : true;
  }
  Dp_DrawLine(1, row, 8, true, false);
  Dp_DrawLine(0,0,10,true,true); // Linie Oben H
  Dp_DrawLine(0,15,10,true,true); // Linie Unten H
  Dp_DrawLine(0,0,16,false,true); // Linie Links V
  Dp_DrawLine(9,0,16,false,true); // Linie Rechts V
  Dp_Draw();
  for (int zeile = row; zeile > 2; zeile--)
  {
    for (int x = 1; x < TE_WIDTH + 1; x++)
    {
      Dp_SetPixel(x, zeile, Dp_GetPixel(x, zeile - 1));
    }
  }
}
void Te_CheckRows()
{
  byte rowWins = 0;
  for (int zeile = TE_HEIGHT; zeile > 0; zeile--)
  {
    bool zeileVoll = true;
    for (int x = 1; x < TE_WIDTH; x++)
    {
      if (!Dp_GetPixel(x, zeile)) // Ist noch ein Stuck frei in der aktuellen Zeile?
      {
        zeileVoll = false;
        break;
      }
    }
    if (zeileVoll) // Ist die aktuelle Zeile voll?
    {
      rowWins++;
      Te_DeleteRow(zeile);
      zeile++;
    }
  }
  if (rowWins > 0)
    Te_AddPoints(random(9, 15) * (10 + pow(3,rowWins) * 10));
}
void Te_Reload()
{
  for (int row = 1; row < TE_HEIGHT + 1; row++)
  {
    Dp_DrawLine(1, row, 8, true, true);
    Dp_Draw();
    delay(60);
  }
  delay(400);
  for (int row = TE_HEIGHT; row >= 1 ; row--)
  {
    Dp_DrawLine(1, row, 8, true, false);
    Dp_Draw();
    delay(60);
  }
  currentStone = St_InitStone();
  points = 0;
  lcd.setCursor(10, 0);
  lcd.print("0     ");
  lcd.setCursor(3, 1);
  lcd.print("             ");
}
void Te_Update(long frameCount)
{
  if (frameCount % 40  == 0)
  {
    currentStone.y++;
    if (St_HitTest(currentStone)) // Stein ist unten Angekommen.
    {
      currentStone.y--;
      for(int i = 0; i < 5; i++)
      {
        St_Print(currentStone, true);
        Dp_Draw();
        delay(60);
        St_Print(currentStone, false);
        Dp_Draw();
        delay(60);
      }
      St_Print(currentStone, true);
      currentStone = St_InitStone();
      Dp_Draw();
      if (St_HitTest(currentStone))
      {
        lcd.setCursor(3, 1);
        lcd.write("Game Over!");
        delay(1000);
        while (!digitalRead(BUTTON_LEFT) || !digitalRead(BUTTON_RIGHT));
        Te_Reload();
      }
      Te_AddPoints(random(1, 4) * 10);
      Te_CheckRows();
      return;
    }
  }
  if(frameCount % 10) // Nach Unten Schieben frei geben (Damit man den Knopf gedruckt lassen kann)
  {
    BUTTON_DOWN_LAST=false;
  }
  if (digitalRead(BUTTON_LEFT))
  {
    if (!BUTTON_LEFT_LAST)
    {
      BUTTON_LEFT_LAST = true;
      // Versuche Stein zu verschieben
      currentStone.x--;
      if (St_HitTest(currentStone))
        currentStone.x++;
    }
  }
  else BUTTON_LEFT_LAST = false;
  if (digitalRead(BUTTON_RIGHT))
  {
    if (!BUTTON_RIGHT_LAST)
    {
      BUTTON_RIGHT_LAST = true;
      // Versuche Stein zu verschieben
      currentStone.x++;
      if (St_HitTest(currentStone))
        currentStone.x--;
    }
  }
  else BUTTON_RIGHT_LAST = false;
  if (digitalRead(BUTTON_ROT))
  {
    if (!BUTTON_ROT_LAST)
    {
      BUTTON_ROT_LAST = true;
      // Versuche Stein zu verschieben
      St_Rotate(¤tStone);
      if (St_HitTest(currentStone))
        St_BackRotate(¤tStone);
    }
  }
  else BUTTON_ROT_LAST = false;
  if (digitalRead(BUTTON_DOWN))
  {
    if (!BUTTON_DOWN_LAST)
    {
      BUTTON_DOWN_LAST = true;
      // Versuche Stein zu verschieben
      currentStone.y++;
      if (St_HitTest(currentStone))
        currentStone.y--;
    }
  }
  else BUTTON_DOWN_LAST = false;
}
 
테트리스를 구현한 아두이노인데요. 
프로그램 연결해서 해봤을때 스위치 세개가 작동이 안됩니다. 
소스 어느부분이 잘못된건지 잘 모르겠어서 글남깁니다ㅠㅠ 
http://kocoafab.cc/make/view/691 
이 작품을 보면서 만들었습니다 
					
										
									 |