קרב זאמה
מהלך הקרב

חניבעל פתח את הקרב, כצפוי, בהסתערות חזיתית של הפילים שלו על מרכז המערך הרומאי, אך מהלך זה פעל כבומרנג, וגרם לו יותר נזק מתועלת. סקיפיו, שצפה מראש את המהלך של יריבו, קידם את פני הפילים בתרועת חצוצרות וקרנות מלחמה, שהבהילו את הפילים, וגרמו לחלקם לפנות לאחור, ולשבש את המערך של הפרשים הנומידיים באגף השמאלי של הצבא הקרתגני. הפילים שהמשיכו בהסתערות גרמו נזק ניכר לרגלים הקלים, שהוצבו לפני המערך הרומי העיקרי, וחלקם לא הספיקו להימלט, אך לאחר מכן תועלו להתקדם במעברים, שסקיפיו פתח במערך צבאו, ולא גרמו נזק רב. הם נפגעו מכידונים וקלעים למיניהם, שהוטלו עליהם משני העברים, יצאו מכלל שליטה וחלקם סבו לאחור ותקפו במנוסתם את הפרשים הקרתגנים באגף הימני של חניבעל. הפילים שנמלטו משדה הקרב הבהילו את הסוסים, ושיבשו את הסדר בקרב הפרשים. כוחות הפרשים של סקיפיו, בפיקוד לאליוס ומסיניסה, ניצלו את הבלבול והמהומה בשורות יריביהם, כדי לתקוף ולהביס את שתי כנפות הפרשים של חניבעל שניצבו מולם, ולהניס אותם משדה הקרב.
לאחר כישלון התקפת הפילים התקדמו כוחות הרגלים של הצבאות היריבים זה לקראת זה. חניבעל קידם את שני הקווים הראשונים של צבאו, אך שמר את הקו השלישי בעתודה, במרחק כ-200 מטר מאחריהם. הקו הראשון של הלגיונות הרומיים (האסטאטים) פתח בהתקפה על קו הרגלים הראשון של חניבעל. בתחילה הצליחו השכירים הגאליים והליגוריים של חניבעל לבלום את התקדמות הלגיונות, והקרב היה שקול, אולם כאשר סקיפיו תיגבר את הקו הראשון שלו במאניפולים של חיילים מהקו השני (פרינקיפים), החלו החיילים הרומיים להדוף לאחור את יריביהם בעצם כוח משקלם והמשמעת העדיפה שלהם. לבסוף נשברה התנגדות הלוחמים בקו הקרתגני הראשון, שבניגוד לרומאים לא קיבלו סיוע מהלוחמים שהוצבו מאחריהם, בקו השני. הם נמלטו לעורף בתקווה למצוא מקלט מאחרי הקו הקרתגני השני, שהורכב מרגלים כבדים יותר, שגויסו מקרתגו ומלוב, אך החיילים בקו השני לא איפשרו להם לעבור דרכם, מחשש שאם יפתחו את שורותיהם, הדבר ישבש את מערכם ויאפשר לרומאים הרודפים להבקיע דרכם. חלק מהנמלטים הנואשים ניסו להבקיע לעצמם דרך בלחימה, והשאר פנו ימינה ושמאלה בניסיון לעקוף את הקו הקרתגני.
תסריט דומה חזר על עצמו כאשר הלגיונות הרומיים תקפו את הקו הקרתגני השני. בתחילה הצליחו הקרתגנים להדוף לאחור את הקו הרומי הראשון, שמערכו השתבש מכיוון ששדה הקרב היה זרוע בגופות וחלקלק מדם, אך סקיפיו שוב תיגבר אותו בכוחות מהקו השני, ומכיוון שהמערך הרומי היה פחות עמוק מהמערך הקרתגני, והיה פרוס על פני חזית רחבה יותר, כוחותיו הצליחו לאגף אותו משני עבריו. החיילים בקו הקרתגני השני נשברו ופנו לנוס, אך החיילים בקו השלישי והאחרון שוב מנעו מהם מעבר דרך שורותיהם, אילצו אותם להימלט ימינה ושמאלה, וחלקם הצטרפו אל האגפים של הקו הקרתגני השלישי והגדילו את רוחב החזית שלו.
בשלב זה של הקרב עצר סקיפיו את התקדמות כוחותיו, הסיג לאחור את האסטאטים שלו, וארגן מחדש את הלגיונות בדרג אחד, שנפרס על חזית רחבה יותר, הן כדי למנוע מחניבעל לאגף את כוחותיו והן כדי לנצל בצורה מיטבית את כלי הנשק שברשותם (חניתות ההטלה). הוא רצה להרוויח זמן, כדי לאפשר לפרשיו לחזור לשדה הקרב מהמרדף אחרי פרשיו של חניבעל. לפי פוליביוס, בשלב זה הכוחות של הצדדים היריבים היו שווים פחות או יותר בגודלם, אך חניבעל נהנה מיתרון משמעותי, משום שהכוחות בקו השלישי שלו הורכבו מחיילים מנוסים ורעננים, שעדיין לא היו מעורבים בקרב, בעוד שמהלגיונות הרומיים רק החיילים הוותיקים ביותר (הטריארים, כ-600 חיילים בכל לגיון), שהוחזקו בקו השלישי, עדיין לא הוטלו למערכה.
למרות השמדת שני הקווים הראשונים של הצבא הקרתגני, נבלמו הרומאים על ידי הלוחמים המנוסים והמצוידים היטב, שהרכיבו את הקו השלישי של חניבעל. התחולל קרב קשה ועקוב מדם שנמשך זמן רב, וכוחותיו של חניבעל החלו להשיג יתרון קל על כוחותיו של סקיפיו (שניסיון האיגוף שלהם נכשל). פוליביוס כתב: "שעה ארוכה היו תוצאות ההתמודדות מוטלות בספק. האנשים נפלו במקום עומדם מתוך עוז החלטה, עד שהגיעו מסיניסה וליליוס כשלוחים משמים ברגע הנכון". הפרשים הנומידיים של מסיניסה והפרשים האיטלקיים של ליליוס חזרו בזמן מהמרדף שלהם אחרי הפרשים הקרתגנים, ותקפו את עורפם של הרגלים של חניבעל. כפי שאירע בקרב קאנאי, התקפת הפרשים הכריעה את הקרב. חייליו הוותיקים של חניבעל, שכותרו והותקפו במקביל מהחזית ומהעורף, המשיכו להילחם בעוז עד הסוף, ורובם נהרגו במקומם. פרשיו של סקיפיו ניהלו מרדף נמרץ בשטח מישורי פתוח אחרי שרידי הצבא הקרתגני, שניסו להימלט משדה הקרב, והרגו או שבו את רובם.
לפי דברי פוליביוס וליוויוס, תבוסתו של חניבעל הייתה שלמה, ורוב צבאו הושמד בשדה הקרב. כ-20 אלף חיילים קרתגנים נהרגו, וכ-18 אלף נפלו בשבי. אבדות הצבא הרומאי היו קלות יחסית, 1,500–2,000 הרוגים וכ-4,000 פצועים. חניבעל עצמו הצליח להימלט משדה הקרב עם קבוצת מלווים קטנה. הוא הבין עתה שהמלחמה אבודה, ושכנע את נכבדי קרתגו לקבל את תנאי הכניעה של הרומאים.