Mam kilka pętli, których potrzebuję w moim programie. Potrafię napisać pseudokod, ale nie jestem do końca pewien, jak napisać je logicznie.
Potrzebuję -
if (num is a multiple of 10) { do this }
if (num is within 11-20, 31-40, 51-60, 71-80, 91-100) { do this }
else { do this } //this part is for 1-10, 21-30, 41-50, 61-70, 81-90
To jest dla gry planszowej węże i drabiny, jeśli ma to więcej sensu w przypadku mojego pytania.
Wyobrażam sobie pierwszą instrukcję if , w której będę musiał użyć modułu. Byłoby if (num == 100%10)
poprawne?
Drugi nie mam pojęcia. Mogę to napisać w ten sposób if (num > 10 && num is < 21 || etc.)
, ale musi być coś mądrzejszego.
c++
comparison
conditional-statements
integer-arithmetic
user3419168
źródło
źródło
Odpowiedzi:
W przypadku pierwszego, aby sprawdzić, czy liczba jest wielokrotnością użycia:
W przypadku drugiego:
Ale to dość gęste i może być lepiej, jeśli po prostu wymień opcje bezpośrednio.
Teraz, gdy masz już lepsze wyobrażenie o tym, co robisz, drugą napisałbym jako:
To ta sama logika, ale używając funkcji, uzyskujemy jaśniejsze pojęcie o tym, co ona oznacza.
źródło
if((num - 1) / 10) % 2 == 1 && num < 100)
- Płakałbym, gdybym to zobaczył.num >= 11
jako (1), że dolna granica jest zakazana, a (2)%
na liczbie ujemnej zwraca również liczbę ujemną. (Muszę przyznać, że używanie& 1
tutaj jest "bezpieczniejsze", ale wymaga też dodatkowej wiedzy.)getRow(num) % 2 == 0
zawarcie funkcji, aby było jasne, jaki jest zamiar.bool inEvenRow(int num){ return getRow(num) % 2 ==0;}
Sztuczka polega na tym, aby szukać pewnego rodzaju podobieństwa między zakresami. Oczywiście zawsze możesz użyć metody „brutalnej siły”:
Ale możesz zauważyć, że jeśli odejmiesz
1
odnum
, będziesz mieć zakresy:Innymi słowy, wszystkie dwucyfrowe liczby, których pierwsza cyfra jest nieparzysta. Następnie musisz wymyślić formułę, która to wyraża. Możesz otrzymać pierwszą cyfrę, dzieląc przez 10, i możesz sprawdzić, czy jest nieparzysta, sprawdzając resztę 1, gdy dzielisz przez 2. Składając to wszystko razem:
Biorąc pod uwagę kompromis między dłuższym, ale możliwym do utrzymania kodem, a krótszym „inteligentnym” kodem, za każdym razem wybrałbym dłuższy i wyraźniejszy. Przynajmniej, jeśli starasz się być sprytny, dołącz komentarz, który dokładnie wyjaśnia, co próbujesz osiągnąć.
Pomaga założyć, że następny programista, który będzie pracował nad kodem, jest uzbrojony i wie, gdzie mieszkasz. :-)
źródło
&& isTensDigitOdd(num)
, być może z komentarzem przed definicją funkcji wyjaśniającym, co robi. Jeśli taki wzorzec istnieje, komentarz wyjaśniający uzasadnienie wzorca jest pouczający w kwestii konserwacji imo.Jeśli używasz GCC lub dowolnego kompilatora obsługującego zakresy wielkości liter, możesz to zrobić, ale Twój kod nie będzie przenośny .
źródło
To jest bardziej dla przyszłych gości niż początkujących. Aby uzyskać bardziej ogólne rozwiązanie podobne do algorytmu, możesz wziąć listę wartości początkowych i końcowych i sprawdzić, czy przekazana wartość znajduje się w jednej z nich:
Dla uproszczenia użyłem polimorficznej lambda (C ++ 14) zamiast jawnego
pair
argumentu. Powinno to również prawdopodobnie trzymać się używania<
i==
być spójne ze standardowymi algorytmami, ale działa tak długo, jakElem
zostało<=
to dla niego zdefiniowane. W każdym razie można go używać w następujący sposób:Jest żywy przykład tutaj .
źródło
Pierwsza jest łatwa. Wystarczy zastosować operator modulo do wartości num:
Ponieważ C ++ ocenia każdą liczbę inną niż 0 jako prawdę, możesz również napisać:
Po drugie, myślę, że jest to bardziej przejrzyste do zrozumienia:
Wzór powtarza się co 20, więc możesz obliczyć modulo 20. Wszystkie elementy, które chcesz, będą w rzędzie, z wyjątkiem tych, które są podzielne przez 20.
Aby je również uzyskać, po prostu użyj num-1 lub lepiej num + 19, aby uniknąć zajmowania się liczbami ujemnymi.
Zakłada się, że wzór będzie się powtarzał w nieskończoność, więc dla 111-120 będzie obowiązywał ponownie i tak dalej. W przeciwnym razie musisz ograniczyć liczby do 100:
źródło
Dzięki kilku dobrym komentarzom w kodzie można go napisać dość zwięźle i czytelnie.
źródło
num % 10 == 0
to to samo, conum
jest wielokrotnością liczby 10.if (num % 10 == 0)
oznacza to samo, co// Check if it's a multiple of 10
nie powinien zajmować się Twoim kodem. To dobrze znany anty-wzór.%
jest anty-wzorcem; oczywiście tak nie jest. Naprawdę, zakładając, że wielu czytelników tego posta będzie początkującymi, nauczenie ich tego stylu pisania komentarzy ma negatywny wpływ na ich rozwój jako programistów.W zasadzie sam wyjaśniłeś odpowiedź, ale na wszelki wypadek oto kod.
źródło
x < 41 x > 50
i umieść nawiasy.operator&&
ma wyższy priorytet niżoperator||
, więc jest w porządku, ale jestem prawie pewien, że GCC i tak ostrzega przed tym.10 < x < 21
jako10 < x && x < 21
niżx > 10 && x < 21
. Łatwiej jest odczytać nierówność, gdy jest w tej samej kolejności, w jakiej zapisujesz ją matematycznie.Możesz się nad tym zastanawiać.
Pierwsza linia
if (x % 10)
działa, ponieważ (a), to wartość, która jest wielokrotnością 10 oblicza jako „0”, inne liczby spowodować ich remainer, (b) wartość 0 w sposóbif
jest uważanyfalse
każda inna wartośćtrue
.Edytować:
Aby przełączać się tam iz powrotem w latach dwudziestych, użyj tej samej sztuczki. Tym razem kluczowa liczba to
10
:x/10
zwraca dowolną liczbę od 0 do 9 jako0
, od 10 do 19 jako1
i tak dalej. Testowanie parzyste lub nieparzyste -& 1
- mówi, czy jest parzyste czy nieparzyste. Ponieważ Twoje zakresy to w rzeczywistości „11 do 20”, przed testowaniem odejmij 1.źródło
Apel o czytelność
Chociaż masz już kilka dobrych odpowiedzi, chciałbym polecić technikę programowania, która sprawi, że Twój kod będzie bardziej czytelny dla jakiegoś przyszłego czytelnika - możesz być za sześć miesięcy, kolega poprosił o dokonanie przeglądu kodu, twój następca ... .
Ma to na celu zawinięcie wszelkich „sprytnych” instrukcji w funkcję, która dokładnie (wraz ze swoją nazwą) pokazuje, co robi. Chociaż istnieje niewielki wpływ na wydajność (wynikający z „narzutu wywołań funkcji”), jest to naprawdę pomijalne w takiej sytuacji w grze.
Po drodze możesz oczyścić swoje dane wejściowe - na przykład przetestować pod kątem „niedozwolonych” wartości. Tak więc możesz skończyć z takim kodem - zobacz, o ile jest bardziej czytelny? „Funkcje pomocnicze” można gdzieś ukryć (nie muszą znajdować się w głównym module: z ich nazwy jasno wynika, co robią):
źródło
YES
iNO
?TRUE
,True
albotrue
? A jakie pliki nagłówkowe musiałbym umieścić w zwykłym C? Więc skręciłem własne. Ciekawe, czy to właśnie spotkało się z negatywną opinią ...Na pierwszy:
będzie dotyczyć:
W przypadku drugiego:
będzie ubiegać się o:
Zasadniczo najpierw robimy,
x-1
aby uzyskać:Następnie dzielimy je,
10
aby otrzymać:Więc sprawdzamy, czy ten wynik jest dziwny.
źródło
Możesz spróbować następujących rzeczy:
źródło
Wiem, że na to pytanie jest tak wiele odpowiedzi, ale moje i tak wrzucę tutaj ...
Zaczerpnięte z książki Steve McConnell's Code Complete , 2. wydanie: „Tabele dostępu po schodach:
Jeszcze innym rodzajem dostępu do stołu jest metoda schodkowa. Ta metoda dostępu nie jest tak bezpośrednia jak struktura indeksu, ale nie marnuje tak dużo miejsca na dane. Ogólna idea struktur schodkowych, zilustrowana na rysunku 18-5, polega na tym, że wpisy w tabeli są prawidłowe dla zakresów danych, a nie dla odrębnych punktów danych.
Rysunek 18-5 Podejście schodkowe kategoryzuje każde wejście poprzez określenie poziomu, na którym uderza w „klatkę schodową”. „Krok”, który uderza, określa jego kategorię.
Na przykład, jeśli piszesz program oceniania, zakres pozycji „B” może wynosić od 75% do 90%. Oto szereg ocen, które pewnego dnia będziesz musiał zaprogramować:
Aby użyć metody schodkowej, należy umieścić górny koniec każdego zakresu w tabeli, a następnie napisać pętlę, aby porównać wynik z górnym końcem każdego zakresu. Kiedy znajdziesz punkt, w którym wynik po raz pierwszy przekracza górną granicę zakresu, wiesz, jaka jest ocena. W przypadku techniki schodkowej należy uważać, aby prawidłowo obsługiwać punkty końcowe zakresów. Oto kod w języku Visual Basic, który przypisuje oceny grupie uczniów na podstawie tego przykładu:
Chociaż jest to prosty przykład, można go łatwo uogólnić, aby uwzględnić wielu uczniów, wiele schematów oceniania (na przykład różne oceny dla różnych poziomów punktów za różne zadania) i zmiany w schemacie oceniania ”.
Code Complete , 2. wydanie, strony 426 - 428 (rozdział 18).
źródło
Jak zauważyli inni, bardziej zwięzłe warunki nie przyspieszą kompilacji ani wykonywania, a także niekoniecznie poprawią czytelność.
Może pomóc w uczynieniu programu bardziej elastycznym, na wypadek gdybyś później zdecydował, że chcesz wersję gry dla maluchów na planszy 6 x 6 lub wersję zaawansowaną (którą możesz grać całą noc) na planszy 40 x 50 .
Więc zakodowałbym to w następujący sposób:
Tak, jest rozwlekły, ale dokładnie wyjaśnia, co dzieje się na planszy.
Gdybym tworzył tę grę do wyświetlania na telefonie lub tablecie, zrobiłbym zmienne ROWS i COLUMNS zamiast stałych, aby można je było ustawić dynamicznie (na początku gry), aby dopasować rozmiar ekranu i orientację.
Pozwoliłbym również na zmianę orientacji ekranu w dowolnym momencie, w trakcie gry - wystarczy zmienić wartości ROWS i COLUMNS, pozostawiając wszystko inne (bieżący numer kwadratu, na którym jest każdy gracz, i kwadraty początku / końca wszystkich węży i drabin) bez zmian. Następnie musisz „tylko” ładnie narysować planszę i napisać kod do swoich animacji (zakładam, że taki był cel twoich
if
wypowiedzi) ...źródło
#define
#define
jest umieszczanie argumentów w nawiasach w miejscach, w których pojawiają się one w rozwinięciu, przy użyciu instrukcji funkcjonalnych . Więc zamiast tego#define finished(num) (num == lastSquare)
powinieneś pisać#define finished(num) ((num) == lastSquare)
. Powodem jest to, że jeśli użyjesz takiej instrukcji z wyrażeniem zawierającym operator o odpowiednio niskim priorytecie, nie otrzymasz oczekiwanej odpowiedzi. W tym przypadku, jeśli nie użyjesz dodatkowych nawiasów, tofinished(a & b)
rozwinie się,(a & b == lastSquare)
co prawie na pewno nie jest tym, czego chcesz.